前端面试干货(四月份前端面试题总指南(下篇))
接着昨天的前端面试题总结写的哈,有在找工作的伙伴,建议仔细阅读!
10.什么是原型链
原型:每个javascript创建的时候都会关联另一个对象,这个对象就是原型,对象会从原型继承属性
构造函数可以通过prototype去寻找他关联的原型,A.prototype就是它关联的原型对象,原型对象可以通过构造器constructor来寻找与自身关联的构造函数
function A () {
}
A.prototype.constructor === A //true
原型链:原型链是由原型对象组成,每个对象都有proto属性,指向该构造函数的原型,proto将对象连接起来组成了原型链
原型链查找机制:当查找对象的属性时,如果实例对象不存在该属性,沿着原型链向上一级查找,直到找到object.prototype(也就是对象原型object.prototype为null),停止查找到返回undefined
function A () {
}
new A().__proto__ === A.prototype //true
原型上的属性和方法被实例共享
function A () {
}
A.prototype.name = 'a'
var a = new A()
var b = new A()
a.name === b.name // true
a.__proto__.name === b.__proto__.name // true
instanceOf原理:instamceOf可以判断实例对象的proto属性与构造函数的prototype是不是同一地址(如果网页中有多个全局环境就会不准确)
function _instanceOf(obj, type) {
var obj = obj.__proto__
var type = type.prototype
while(true) {
if (obj == null) {
return false
}
if (obj == type) {
return true
}
obj = obj.__proto__
}
}
var a = [1, 2, 3]
_instanceOf(a, Array)
11.深拷贝和浅拷贝
浅拷贝只是复制引用,新旧对象共享一块内存,一般把第一层拷贝到一个对象上,改变其中一个另一个也会改变
var obj = {
name: 'a',
age: 18,
arr: [1, 2]
}
function shallowCopy(obj) {
var newObj = {};
for (var prop in obj) {
if (obj.hasOwnProperty(prop)) { // 过滤掉原型上的属性
newObj[prop] = obj[prop];
}
}
return newObj;
}
var obj1 = shallowCopy(obj)
var obj2 = obj
obj1.name = 'b'
obj2.age = 20
obj2.arr[0] = 3
obj1.arr[0] = 4
console.log(obj) // {name: "a", age: 20, arr: [4, 2]}
console.log(obj1) // {name: "b", age: 18, arr: [4, 2]}
console.log(obj2) // {name: "a", age: 20, arr: [4, 2]}
我们通过浅拷贝得到obj1,改变obj1的name,obj不会发生改变,通过赋值得到obj2,obj2改变age值obj的值也会被改变。说明赋值得到的对象只是改变了指针,浅拷贝是创建了新对象。
我们通过obj2和obj1都改变的值,发现obj,ob1,obj2都发生了改变,所以无论是浅拷贝还是赋值都会改变原始数据(浅拷贝只拷贝了一层对象的属性)
深拷贝:复制并创建一个一摸一样的对象(递归复制了所有层级),不共享内存,改变其中一个另一个不会改变
var obj = {
name: 'a',
age: 18,
arr: [1, 2]
}
function copy (obj) {
var newobj = Array.isArray(obj) ? [] : {};
if(typeof obj !== 'object'){
return;
}
for(var i in obj){
if (obj.hasOwnProperty(i)) {
newobj[i] = typeof obj[i] === 'object' ? copy(obj[i]) : obj[i];
}
}
return newobj
}
var copyObj = copy(obj)
copyObj.arr[0] = 3
console.log(copyObj) //{name: "a", age: 20, arr: [3, 2]}
console.log(obj) //{name: "a", age: 20, arr: [1, 2]}
12.实现继承
原型链继承(在实例化一个类时,新创建的对象复制了父类构造函数的属性和方法,并将proto指向父类的原型对象,当在子类上找不到对应的属性和方法时,将会在父类实例上去找。)
function Big () {
this.age = [1, 2, 3]
}
Big.prototype.getAge = function () {
return this.age
}
function Small() {}
Small.prototype = new Big()
var small = new Small()
console.log(small.age) // [1, 2, 3]
console.log(small.getAge()) // [1, 2, 3]
缺点1:引用缺陷(修改其中一个Small实例的父类变量会影响所有继承Big的实例)
small.age[0] = 12
var small1 = new Small()
console.log(small1.age) // [12, 2, 3]
console.log(small.age) // [12, 2, 3]
缺点2:无法为不同的实例初始化继承来的属性
function Big (name) {
this.age = [1, 2, 3]
this.name = name
}
Big.prototype.getAge = function () {
return this.age
}
function Small() {}
Small.prototype = new Big('small')
var small = new Small()
var small1 = new Small()
console.log(small1.name) // small
console.log(small.name) // small
构造函数继承(在子类的构造函数中执行父类的构造函数,并为其绑定子类的this,让父类的构造函数把成员属性和方法都挂到子类的this上)
function Big (name) {
this.age = [1, 2, 3]
this.name = name
}
Big.prototype.getAge = function () {
return this.age
}
function Small(name) {
Big.apply(this, arguments)
}
var small = new Small('small')
var small1 = new Small('small1')
console.log(small.name) // small
console.log(small1.name) // small1
small.age[0] = 12
console.log(small.age) // [12, 2, 3]
console.log(small1.age) // [1, 2, 3]
缺点:无法访问原型上的方法
small.getAge() //small.getAge is not a function
组合式继承(将原型链继承和构造函数继承组合到一起, 综合了原型链继承和构造函数继承的优点)
function Big (name) {
this.age = [1, 2, 3]
this.name = name
}
Big.prototype.getAge = function () {
return this.age
}
function Small(name) {
Big.apply(this, arguments)
}
Small.prototype = new Big()
var small = new Small('small')
var small1 = new Small('small1')
console.log(small.name) // small
console.log(small1.name) // small1
small.age[0] = 12
console.log(small.age) // [12, 2, 3]
console.log(small1.age) // [1, 2, 3]
console.log(small.getAge()) // [12, 2, 3]
console.log(small1.getAge()) // [1, 2, 3]
小缺点:调用了两次父类构造函数
寄生组合式继承(在组合继承的基础上减少一次多余的调用父类构造函数)
function Big (name) {
this.age = [1, 2, 3]
this.name = name
}
Big.prototype.getAge = function () {
return this.age
}
function Small(name) {
Big.apply(this, arguments)
}
// 对父类原型进行拷贝,否则子类原型和父类原型指向同一个对象,修改子类原型会影响父类
Small.prototype = Object.create(Big.prototype)
var small = new Small('small')
var small1 = new Small('small1')
console.log(small.name) // small
console.log(small1.name) // small1
small.age[0] = 12
console.log(small.age) // [12, 2, 3]
console.log(small1.age) // [1, 2, 3]
console.log(small.getAge()) // [12, 2, 3]
console.log(small1.getAge()) // [1, 2, 3]
注意:对父类原型进行拷贝后赋值给子类原型,因此Small上的constructor属性被重写,需要修复Small.prototype.constructor = Dog;
extends继承(class和extends是es6新增的,class创建一个类,extends实现继承)
class Big {
constructor(age) {
this.age = age;
}
getAge () {
return this.age
}
}
class Small extends Big {
constructor(age) {
super(age)
}
}
var small = new Small([1, 2, 3])
var small1 = new Small([12, 2, 3])
small.age[0] = 13
console.log(small.age) // [13, 2, 3]
console.log(small.getAge()) // [13, 2, 3]
console.log(small1.age) // [12, 2, 3]
console.log(small1.getAge()) // [12, 2, 3]
浏览器网络
1.常用http状态码
200 成功状态码
301 永久重定向,302 临时重定向
400 请求语法错误, 401 请求需要http认证,403 不允许访问资源,404 资源未找到
500 服务器内部错误,502 访问时出错,503 服务器忙,无法响应
2.https原理
http协议:客户端浏览器与web服务器之间的应用层通讯协议
https协议:HTTP+SSL/TLS,http下加入SSL层,https安全基础时SSL,用于安全的HTTP数据传输
https优势:内容经过对称加密,每个连接会生成唯一的加密密钥,内容经过完整性校验,第三方无法伪造身份
使用对称加密(加密和解密使用的是同一个密钥)被中间人拦截,中间人可以获取密钥,就可以对传输的信息进行窥视和篡改
使用非对称密钥(双方必须协商一对密钥,一个私钥和一个公钥)用私钥加密的数据,只有对应的公钥才能解密,用公钥加密的数据,只有对应的私钥才能解密,弊端:RSA算法很慢
非对称密钥+对称密钥(结合两者优点)
客户端获取公钥确认服务器身份通过SSL证书,客户端接受到服务端发来的SSL证书给客户端。
3.前端安全
XSS攻击:注入恶意代码来攻击。攻击者在目标网站上注入恶意代码,被攻击者登陆网站执行这些恶意代码,这些脚本可以读取 cookie,session tokens,或者其它敏感的网站信息,对用户进行钓鱼欺诈(打开新标签跳转,新标签存在恶意代码,跳转到伪造的页面),网页植入广告等。
XSS攻击防御手段:禁止JavaScript读取某些敏感cookie,限制输入内容和长度控制,检测是否有恶意代码注入
CSRF攻击:诱导用户进入第三方,获取到登录凭证,冒充用户对被攻击的站点执行操作,导致账号被劫持
防御CSRF攻击:验证token(请求服务器时,返回token,每个请求需要加上token),
5.浏览器缓存
浏览器每次发起请求,都会在浏览器缓存中查找请求结果和缓存标识,浏览器每次拿到的数据会将结果和标识存入浏览器中
强制缓存:当浏览器向服务器发起请求时,服务器会将缓存规则放入HTTP响应报文的HTTP头中和请求结果一起返回给浏览器,控制强制缓存的字段分别是Expires和Cache-Control,其中Cache-Control优先级比Expires高。
协商缓存:强制缓存失效后,浏览器携带缓存标识向服务器发起请求,由服务器根据缓存标识决定是否使用缓存的过程。(协商缓存生效,服务器返回304,资源未更新,协商缓存失效,服务器返回200,资源更新重新缓存)
详情可以看这篇文章彻底理解浏览器的缓存机制
框架
1.什么是vue生命周期
每个vue实例在被创建之前都要经过一系列初始化过程,这个过程就是vue生命周期。(开始创建、初始化数据、编译模板、挂载Dom→渲染、更新→渲染、卸载等一系列过程)
beforeCreate: 完成实例初始化,this指向被创建的实例,data,computed,watch,mothods方法和数据都不可以访问
created: 实例创建完成,data,computed,watch,methods可被访问,未挂载dom,可对data进行操作,操作dom需放到nextTick中
beforeMount: 有了el,找到对应的template编译成render函数
mounted: 完成挂载dom和渲染,可以对dom进行操作,并获取到dom节点,可以发起后端请求拿到数据
beforeUpdate: 数据更新之前访问现有dom,可以手动移除已添加事件的监听
updated: 组件dom已完成更新,可执行依赖的dom 操作,不要操作数据会陷入死循环
activated: keep-alive缓存组件激活时调用
deactivated keep-alive移除时调用
beforeDestroy: 实例销毁之前调用,可以销毁定时器
destroyed: 组件已经被销毁
2.第一次页面加载会触发哪几个钩子
会触发beforeCreate, created, beforeMount, mounted
3.created和mounted的区别
created:在模板渲染成html前调用,即通常初始化某些属性值,然后再渲染成视图。
mounted:在模板渲染成html后调用,通常是初始化页面完成后,再对html的dom节点进行一些需要的操作。
4.hash模式和history模式
在vue的路由配置中有mode选项 最直观的区别就是在url中 hash 带了一个很丑的 # 而history是没有#的。
hash 虽然出现在 URL 中,但不会被包括在 HTTP 请求中,对后端完全没有影响,因此改变 hash 不会重新加载页面。
history利用了HTML5中新增的 pushState() 和 replaceState() 方法。这两个方法应用于浏览器的历史记录栈,在当前已有的 back、forward、go 的基础之上,它们提供了对历史记录进行修改的功能。只是当它们执行修改时,虽然改变了当前的 URL,但浏览器不会立即向后端发送请求。
history模式需要后台配置支持
5.computed和watch区别
computed: 依赖的属性值发生改变才会重新计算,得出最后的值
watch: 当依赖的data的数据变化,执行回调(可以观察数据的某些变化,来做一些事情)
6.vue中key的作用
【前端面试干货(四月份前端面试题总指南(下篇))】key是给每一个vnode的唯一id,可以依靠key,更准确, 更快的拿到oldVnode中对应的vnode节点。
7.vue的两个核心点
数据驱动:ViewModel,保证视图的一致性
组件系统:组件化,封装可复用的组件,页面上每个独立的区域都可以看成一个组件,组件可以自由组合成页面
8.SPA首屏加载慢如何解决
使用路由懒加载
使用SSR渲染
优化webpack打包体积
图片使用CDN加速
9.vue禁止弹窗后的屏幕滚动
主要是是写一个点击出现弹窗禁止屏幕滚动的方法,关闭弹窗屏幕可以正常滚动
methods : {
//禁止滚动
stop(){
var mo=function(e){e.preventDefault();
};
document.body.style.overflow='hidden';
document.addEventListener("touchmove",mo,false);
//禁止页面滑动
},
/取消滑动限制/
move(){
var mo=function(e){e.preventDefault();
};
document.body.style.overflow='';
//出现滚动条
document.removeEventListener("touchmove",mo,false);
}
}
10.Vuex中actions和mutations的区别
action主要处理的是异步的操作,mutation必须同步执行,而action就不受这样的限制,也就是说action中我们既可以处理同步,也可以处理异步的操作
action改变状态,最后是通过提交mutation
如果有错误或者不严谨的地方,请务必给予指正,十分感谢。
还有前端2020全套教学视频和学习线路图可以找学姐领取哦(xuejie077 备注来源哦)我们一起学习吧!
推荐阅读
- 人工智能|干货!人体姿态估计与运动预测
- Jsr303做前端数据校验
- 2018国考外交部面试演讲不再难——只需把握好三点
- iOS面试题--基础
- 干货来袭(自我管理(来几款撩人的APP))
- 7、前端--jQuery简介、基本选择器、基本筛选器、属性选择器、表单选择器、筛选器方法、节点操作、绑定事件
- 前端代码|前端代码 返回顶部 backToTop
- java|java 常用知识点链接
- 前端|web前端dya07--ES6高级语法的转化&render&vue与webpack&export
- 前端自学笔记01