腾讯实习面试总结(一)

项目

vue的插件用过哪些?

vue router和vuex。

Vue Router 是 Vue.js官方的路由管理器。它和 Vue.js 的核心深度集成,让构建单页面应用变得易如反掌。包含的功能有:

  • 嵌套的路由/视图表
  • 模块化的、基于组件的路由配置
  • 路由参数、查询、通配符
  • 基于 Vue.js 过渡系统的视图过渡效果
  • 细粒度的导航控制
  • 带有自动激活的 CSS class 的链接
  • HTML5 历史模式或 hash 模式,在 IE9 中自动降级
  • 自定义的滚动条行为

Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式。它采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化。

vuex是什么?

vuex是vue.js提供的一个状态管理工具。说了一下之前项目中遇到的多用户登录验证的问题,用的是sessionStorage存储登录的状态,比较了为什么没有用vuex(当页面强制刷新之后vuex状态会被清空,面试官感到了怀疑)。

sessionStorage localStorage和cookie?

localStorage会一直存储状态直到手动删除,这里因为做的是登录的用户验证,所以需要有一个会话时间的限制。

cookie和HTML的storage比起来,存储的数据量更小一点。

项目中印象最深的是什么?

这个回答得不好,没有说得很具体,只说了一些知识点的储备和一些bug的修改。

数据交互,MVC模型和MVVM模型?vue是怎么实现的MVVM?

ExtJs是MVC模型,视图和数据分离,用控制器实现一些基本的操作,但是需要进行事件监听,操作dom结构,性能不高。

Vue.js是MVVM模型,通过在view model层进行数据绑定,数据驱动视图,数据发生改变后视图也发生改变,不需要事件监听和

JS基础

数组的基本操作

  • 删除第二个数:splice
  • 删除/添加第一个数:shift/unshift
  • 删除/添加最后一个数:pop/push
  • 数组排序:sort
    • 一个可选的参数,作为排序顺序的函数
    • 返回一个用于说明这两个值的相对顺序的数字
    • 从小到大返回负数(a-b),从大到小返回正数(b-a)

对象的继承

1.原型链

重写子类型的原型对象,代之以一个新类型的实例。

1
SubType.prototype = new SuperType();
  • 构造函数、原型、实例的关系:
    • 每个构造函数都有一个原型对象;
    • 原型对象都包含一个指向构造函数的指针;
    • 实例包含一个指向原型对象的内部指针
  • 所有引用类型都默认继承了Object,这个继承是通过原型链实现的
  • 确定原型和实例之间的关系:instanceof操作符 / isPrototypeOf()方法
  • 原型链的问题:
    • 引用类型的值会共享,所有的子类型的实例都会共享引用类型的属性,一个实例修改了这个属性,另一个实例也会被修改
    • 在创建子类型的实例时,不能向超类型的构造函数中传递参数

2.借用构造函数(伪造对象或经典继承)

在子类型构造函数的内部调用超类型的构造函数。

1
2
3
function SubType(){
SuperType.call(this);
}
  • 可以在子类型构造函数中传递参数
  • 借用构造函数的问题:方法都在构造函数中定义,无法做到函数复用(不同实例的同名方法是相同的)

3.组合继承

借用构造函数继承属性,原型链继承方法。(最常用的继承模式)

  • 组合继承的问题:无论什么情况下,都会调用两次超类型的构造函数。一次是在创建子类型原型的时候,一次是在子类型构造函数的内部。(解决方法:寄生组合式继承)

4.原型式继承

不需要构造函数,基于已有的对象创建新对象

1
2
3
4
5
function object(o){
function F(){}
F.prototype = o;
return new F();
}

ES5新增了Object.create() 规范了原型式继承

  • 原型式继承的问题:引用类型属性共享(和原型链类似)

5.寄生式继承

创建一个仅用于封装继承过程的函数,该函数在内部以某种方式来增强对象,最后再返回对象。

1
2
3
4
5
6
7
function createAnother(original){
var clone = object(original) //通过调用函数创建一个新对象
clone.sayHi = function(){ //以某种方式增强这个对象
...
}
return clone;
}
  • 在主要考虑对象而不是自定义类型和构造函数的情况下,可以使用寄生式继承。
  • 寄生式继承的问题:使用寄生式继承为对象添加函数,会由于不能做到函数复用降低效率(和构造函数模式类似)

6.寄生组合式继承

通过借用构造函数继承属性,通过原型链的混成形式继承方法。不必为了指定子类型的原型调用超类型的构造函数。本质上就是使用寄生式继承来继承超类型的原型,再将结果指定给子类型的原型。

1
2
3
4
5
function inheritPrototype(subType,superType){
var prototye = object(superType .prototype) //创建对象
prototype.constructor = subType //增强对象,弥补因为重写原型而失去的默认的constructor属性
subType.prototype = prototype //指定对象
}

闭包

闭包是指有权访问另一个函数作用域中的变量的函数。常见方式是在一个函数内部创建另一个函数。

闭包的用途

  • 可以读取函数内部的变量
  • 可以让这些变量的值始终保持在内存中
  • 在没有class的概念之前,可以使用闭包封装私有变量和私有方法

跨域

跨域是指一个域下的文档或脚本试图去请求另一个域下的资源。

广义的跨域

  1. 资源跳转:A链接、重定向、表单提交
  2. 资源嵌入:link、script、img、frame等dom标签,样式中的background:url()、@font-face()等文件外链
  3. 脚本请求:js发起的ajax请求、dom和js对象的跨域操作

狭义的跨域

浏览器同源策略限制的一类请求场景

同源:协议、域名、端口都相同

同源策略:

  • 通常浏览器允许进行跨域写操作(Cross-origin writes),如链接,重定向;
  • 通常浏览器允许跨域资源嵌入(Cross-origin embedding),如 img、script 标签;
  • 通常浏览器不允许跨域读操作(Cross-origin reads)。*

跨域解决方案

1.jsonp

利用script标签没有跨域的限制,在页面上引入不同域上的js脚本文件是可以的,所以可以通过script标签请求跨域的地址,再出发回调函数处理数据。

  • 优点:兼容性好(兼容低版本IE)
  • 缺点:1.JSONP只支持GET请求; 2.XMLHttpRequest相对于JSONP有着更好的错误处理机制

2.document.domain+iframe

实现原理:两个页面都通过js强制设置document.domain为基础主域,就实现了同域。

该方式只能用于二级域名相同的情况下(主域相同,子域不同),比如 a.test.com 和 b.test.com 适用于该方式。

3.location.hash+iframe

实现原理: a.html 欲与 c.html 跨域相互通信,通过中间页 b.html 来实现。 三个页面,不同域之间利用 iframe 的 location.hash 传值,相同域之间直接 js 访问来通信。

4.window.name+ifame

利用window.name属性。name值在不同域名的页面加载后依然存在,并可以支持较长的name值(2MB)

通过 iframe 的 src 属性由外域转向本地域,跨域数据即由 iframe 的 window.name 从外域传递到本地域。这个就巧妙地绕过了浏览器的跨域访问限制,但同时它又是安全操作。

5.postMessage

postMessage 是 HTML5 XMLHttpRequest Level 2 中的 API,且是为数不多可以跨域操作的 window 属性之一。

1
iframe.contentWindow.postMessage()

6.CORS跨域资源共享

CORS 是W3C 推荐的一种新的官方方案,能使服务器支持 XMLHttpRequest 的跨域请求。只需要在服务器端设置Access-Control-Allow-Origin就可以开启,该属性表示哪些域名可以访问资源。

目前所有浏览器都支持该功能(IE 8 和 9 需要通过 XDomainRequest 来实现)

值得注意的是,通常使用CORS时,异步请求会被分为简单请求和非简单请求,非简单请求的区别是会先发一次预检请求。

7.nginx代理跨域

实现思路:通过 nginx 配置一个代理服务器(域名与 domain1 相同,端口不同)做跳板机,反向代理访问 domain2 接口,并且可以顺便修改 cookie 中 domain 信息,方便当前域 cookie 写入,实现跨域登录。

8.node.js中间件代理跨域

实现原理:同源策略是浏览器需要遵循的标准,而如果是服务器向服务器请求就无需遵循同源策略。

通过开启一个代理服务器实现数据的转发。代理服务器需要设置CORS首部字段。

  1. 非Vue框架需要两次跨域

  2. Vue框架只需要一次跨域

    node+webpack+webpack-dev-server代理接口跨域。由于vue渲染服务和接口代理服务都是webpack-dev-server同一个,所以浏览器页面和代理接口之间不再需要跨域了。

9.WebSocket协议跨域

Websocket是HTML5的一种新的协议,实现了浏览器与服务器的全双工通信,同时允许跨域通讯,是server push技术的一种很好的实现。

安全

XSS

攻击

  1. 反射型

    反射型xss一般出现在URL参数中及网站搜索栏中,由于需要点击包含恶意代码的URL才可以触发,并且只能触发一次,所以也被称为“非持久性xss”。

  2. 存储型

    存储型xss一出现在网站留言板,评论处,个人资料处,等需要用户可以对网站写入数据的地方。比如一个论坛评论处由于对用户输入过滤不严格,导致攻击者在写入一段窃取cookie的恶意JavaScript代码到评论处,这段恶意代码会写入数据库,当其他用户浏览这个写入代码的页面时,网站从数据库中读取恶意代码显示到网页中被浏览器执行,导致用户cookie被窃取,攻击者无需受害者密码即可登录账户。所以也被称作“持久性xss”。持久性xss比反射型xss危害要大的多。

  3. DOM型

    DOM xss是基于dom文档对象模型,前端脚本通过dom动态修改页面,由于不与服务端进行交互,而且代码是可见的,从前端获取dom中的数据在本地执行。

    常见的可以操纵dom的对象:URL,localtion,referrer等

防御

  1. 编码:对用户输入的数据进行HTML Entity编码
  2. 过滤:白名单或黑名单过滤。移除用户上传的DOM属性、script、style、iframe节点
  3. HttpOnly:对于设置了httponly属性的网页,浏览器将禁止页面的javascript访问cooike。这可以很好的解决产生XSS后的Cookie劫持问题。
  4. 浏览器过滤:filter/auditor:X-XSS-Protection。就是浏览器内置的一种 XSS 防范措施。是 HTTP 的一个响应头字段,要开启很简单,在服务器的响应报文里加上这个字段即可。浏览器接收到这个字段则会启用对应的 XSS 防范模块。针对反射型XSS
  5. CSP(内容安全策略):是一个附加的安全层,有助于检测并缓解某些类型的攻击,包括跨站脚本(XSS)和数据注入攻击。通常可以通过HTTP Header中的Content-Security-Policy来开启CSP。

CSRF

攻击

跨站请求伪造,是一种挟持用户在当前已登录的Web应用上执行非本意的操作的攻击方法。

防御

  1. SameSite:对Cookie设置该属性,设置Cookie不随着跨域请求发送。但不是所有浏览器都兼容。
  2. 验证Referer:来判断该请求是否为第三方网站发起的
  3. Token:服务器下发一个随机Token,每次发起请求时携带Token,服务器验证是否有效。

SQL注入