1.模拟实现一个 bind 的效果
实现bind之前,我们首先要知道它做了哪些事情。
1. 对于普通函数,绑定this指向
2. 对于构造函数,要保证原函数的原型对象上的属性不能丢失
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18Function.prototype.bind = function (context, ...args) { // 异常处理 if (typeof this !== "function") { throw new Error("Function.prototype.bind error"); } // 保存this的值,它代表调用 bind 的函数 var self = this; var fNOP = function () {}; var fbound = function () { self.apply(this instanceof self ? this : context, args.concat(Array.prototype.slice.call(arguments))); } fNOP.prototype = this.prototype; fbound.prototype = new fNOP(); return fbound; }
2.谈谈你对JS中this的理解
其实JS中的this是一个非常简单的东西,只需要理解它的执行规则就OK。
call/apply/bind可以显示绑定, 这里就不说了。
主要这些场隐式绑定的场景讨论:
1.全局上下文
1.直接调用函数
3.对象.方法的形式调用
4.DOM事件绑定(特殊)
5.new构造函数绑定
6.箭头函数
- 全局上下文
全局上下文默认this指向window, 严格模式下指向undefined。 - 直接调用函数
1
2
3
4
5
6
7
8let obj = { a: function() { console.log(this); } } let func = obj.a; func();
这种情况是直接调用。this相当于全局上下文的情况。
- 对象.方法的形式调用
还是刚刚的例子,我如果这样写:
1
2obj.a();
这就是对象.方法的情况,this指向这个对象
- DOM事件绑定
onclick和addEventerListener中 this 默认指向绑定事件的元素。
IE比较奇异,使用attachEvent,里面的this默认指向window。 - new+构造函数
此时构造函数中的this指向实例对象。 - 箭头函数
箭头函数没有this, 因此也不能绑定。里面的this会指向当前最近的非箭头函数的this,找不到就是window(严格模式是undefined)。比如:
1
2
3
4
5
6
7
8
9
10let obj = { a: function() { let do = () => { console.log(this); } do(); } } obj.a(); // 找到最近的非箭头函数a,a现在绑定着obj, 因此箭头函数中的this是obj
3.JS中浅拷贝的手段有哪些?
首先什么是拷贝?
首先来直观的感受一下什么是拷贝。
1
2
3
4
5
6let arr = [1, 2, 3]; let newArr = arr; newArr[0] = 100; console.log(arr);//[100, 2, 3]
这是直接赋值的情况,不涉及任何拷贝。当改变newArr的时候,由于是同一个引用,arr指向的值也跟着改变。
现在进行浅拷贝:
1
2
3
4
5
6let arr = [1, 2, 3]; let newArr = arr.slice(); newArr[0] = 100; console.log(arr);//[1, 2, 3]
当修改newArr的时候,arr的值并不改变。什么原因?
因为这里newArr是arr浅拷贝后的结果,newArr和arr现在引用的已经不是同一块空间啦!
这就是浅拷贝!
但是这又会带来一个潜在的问题:
1
2
3
4
5
6let arr = [1, 2, {val: 4}]; let newArr = arr.slice(); newArr[2].val = 1000; console.log(arr);//[ 1, 2, { val: 1000 } ]
咦!不是已经不是同一块空间的引用了吗?为什么改变了newArr改变了第二个元素的val值,arr也跟着变了。
这就是浅拷贝的限制所在了。 它只能拷贝一层对象。如果有对象的嵌套,那么浅拷贝将无能为力。 但幸运的是,深拷贝就是为了解决这个问题而生的,它能 解决无限极的对象嵌套问题,实现彻底的拷贝。当然,这是我们下一篇的重点。 现在先让大家有一个基本的概念。
接下来,我们来研究一下JS中实现浅拷贝到底有多少种方式?
- 手动实现
1
2
3
4
5
6
7
8
9
10
11
12
13
14const shallowClone = (target) => { if (typeof target === 'object' && target !== null) { const cloneTarget = Array.isArray(target) ? []: {}; for (let prop in target) { if (target.hasOwnProperty(prop)) { cloneTarget[prop] = target[prop]; } } return cloneTarget; } else { return target; } }
- Object.assign
但是需要注意的是,Object.assgin() 拷贝的是对象的属性的引用,而不是对象本身。
1
2
3
4let obj = { name: 'sy', age: 18 }; const obj2 = Object.assign({}, obj, {name: 'sss'}); console.log(obj2);//{ name: 'sss', age: 18 }
- concat浅拷贝数组
1
2
3
4
5let arr = [1, 2, 3]; let newArr = arr.concat(); newArr[1] = 100; console.log(arr);//[ 1, 2, 3 ]
- slice浅拷贝
- …展开运算符
1
2
3let arr = [1, 2, 3]; let newArr = [...arr];//跟arr.slice()是一样的效果
最后
以上就是机智音响最近收集整理的关于每天一点面试题(3)的全部内容,更多相关每天一点面试题(3)内容请搜索靠谱客的其他文章。
发表评论 取消回复