前端20道大厂面试题,你能答出几个呢?
2019/09/20 16:32 分类: 技术交流 浏览:0
1. new的实现原理是什么?
new 的实现原理:
-
创建一个空对象,构造函数中的this指向这个空对象
-
这个新对象被执行 [[原型]] 连接
-
执行构造函数方法,属性和方法被添加到this引用的对象中
-
如果构造函数中没有返回其它对象,那么返回this,即创建的这个的新对象,否则,返回构造函数中返回的对象。
2. 如何正确判断this的指向?
如果用一句话说明 this 的指向,那么即是: 谁调用它,this 就指向谁。
但是仅通过这句话,我们很多时候并不能准确判断 this 的指向。因此我们需要借助一些规则去帮助自己:
this 的指向可以按照以下顺序判断:
全局环境中的 this
浏览器环境:无论是否在严格模式下,在全局执行环境中(在任何函数体外部)this 都指向全局对象 window;
node 环境:无论是否在严格模式下,在全局执行环境中(在任何函数体外部),this 都是空对象 {};
是否是 new 绑定
如果是 new 绑定,并且构造函数中没有返回 function 或者是 object,那么 this 指向这个新对象。如下:
构造函数返回值不是 function 或 object。new Super() 返回的是 this 对象。
构造函数返回值是 function 或 object,new Super()是返回的是Super种返回的对象。
函数是否通过 call,apply 调用,或者使用了 bind 绑定,如果是,那么this绑定的就是指定的对象【归结为显式绑定】。
这里同样需要注意一种特殊情况,如果 call,apply 或者 bind 传入的第一个参数值是 undefined 或者 null,严格模式下 this 的值为传入的值 null /undefined。非严格模式下,实际应用的默认绑定规则,this 指向全局对象(node环境为global,浏览器环境为window)
隐式绑定,函数的调用是在某个对象上触发的,即调用位置上存在上下文对象。典型的隐式调用为: xxx.fn()
默认绑定,在不能应用其它绑定规则时使用的默认规则,通常是独立函数调用。
非严格模式:node环境,指向全局对象 global,浏览器环境,指向全局对象 window。
严格模式:执行 undefined
箭头函数的情况:
箭头函数没有自己的this,继承外层上下文绑定的this。
3. 深拷贝和浅拷贝的区别是什么?实现一个深拷贝
查看解析
深拷贝和浅拷贝是针对复杂数据类型来说的,浅拷贝只拷贝一层,而深拷贝是层层拷贝。
深拷贝
深拷贝复制变量值,对于非基本类型的变量,则递归至基本类型变量后,再复制。深拷贝后的对象与原来的对象是完全隔离的,互不影响,对一个对象的修改并不会影响另一个对象。
浅拷贝
浅拷贝是会将对象的每个属性进行依次复制,但是当对象的属性值是引用类型时,实质复制的是其引用,当引用指向的值改变时也会跟着变化。
可以使用 for in、 Object.assign、 扩展运算符 ... 、Array.prototype.slice()、Array.prototype.concat() 等,例如:
可以看出浅拷贝只最第一层属性进行了拷贝,当第一层的属性值是基本数据类型时,新的对象和原对象互不影响,但是如果第一层的属性值是复杂数据类型,那么新对象和原对象的属性值其指向的是同一块内存地址。
深拷贝实现
1.深拷贝最简单的实现是: JSON.parse(JSON.stringify(obj))
JSON.parse(JSON.stringify(obj)) 是最简单的实现方式,但是有一些缺陷:
-
对象的属性值是函数时,无法拷贝。
-
原型链上的属性无法拷贝
-
不能正确的处理 Date 类型的数据
-
不能处理 RegExp
-
会忽略 symbol
-
会忽略 undefined
2.实现一个 deepClone 函数
-
如果是基本数据类型,直接返回
-
如果是 RegExp 或者 Date 类型,返回对应类型
-
如果是复杂数据类型,递归。
-
考虑循环引用的问题
4. call/apply 的实现原理是什么?
查看解析
call 和 apply 的功能相同,都是改变 this 的执行,并立即执行函数。区别在于传参方式不同。
-
func.call(thisArg, arg1, arg2, ...):第一个参数是 this 指向的对象,其它参数依次传入。
-
func.apply(thisArg, [argsArray]):第一个参数是 this 指向的对象,第二个参数是数组或类数组。
一起思考一下,如何模拟实现 call ?
首先,我们知道,函数都可以调用 call,说明 call 是函数原型上的方法,所有的实例都可以调用。即: Function.prototype.call。
-
在 call 方法中获取调用call()函数
-
如果第一个参数没有传入,那么默认指向 window / global(非严格模式)
-
传入 call 的第一个参数是 this 指向的对象,根据隐式绑定的规则,我们知道 obj.foo(), foo() 中的 this 指向 obj;因此我们可以这样调用函数 thisArgs.func(...args)
-
返回执行结果
apply 的实现思路和 call 一致,仅参数处理略有差别。如下:
5. 柯里化函数实现
6. 如何让 (a == 1 && a == 2 && a == 3) 的值为true?
7. 什么是BFC?BFC的布局规则是什么?如何创建BFC?
8. 异步加载JS脚本的方式有哪些?
9. ES5有几种方式可以实现继承?分别有哪些优缺点?
10. 隐藏页面中的某个元素的方法有哪些?
11. let、const、var 的区别有哪些?
12. 说一说你对JS执行上下文栈和作用域链的理解?
13. 防抖函数的作用是什么?请实现一个防抖函数
14. 节流函数的作用是什么?有哪些应用场景,请实现一个节流函数
15. 什么是闭包?闭包的作用是什么?
16. 实现 Promise.all 方法
17. 请实现一个 flattenDeep 函数,把嵌套的数组扁平化
18. 请实现一个 uniq 函数,实现数组去重
19. 可迭代对象有哪些特点
20. JSONP 的原理是什么?
赞 0