预警:【你不知道的javascript】开头的文章,是用来总结书籍《你不知道的Javascript》中我不熟悉的知识,单纯的用来巩固学到的知识,和加深记忆。
可能有些地方我理解的不透彻,所以不能够保证内容的正确性,欢迎指正。
重点知识
- this 指向 取决于函数的【调用位置】,不像变量的作用域取决于声明的位置
- 默认绑定
- this 指向函数的调用位置,一般是全局
- 优先级最低的绑定
- 隐式绑定
- 用 obj.x 调用函数时,绑定给 obj(函数是做为某个对象的属性调用的)
- 隐式丢失: 先用 obj.xx 赋值,得到返回值后,再运行返回值,就应用了默认绑定
- 显示绑定
- 硬绑定 call / apply / bind
- call 接受多个参数
- apply 接受参数数组
- 怎么记住 call 和 apply 接受参数分别时啥样的呢?call单词字母少,但是参数多
- bind 返回一个函数
- 要学会手写实现 call / apply/ bind 方法,其中call 和 apply 方法类似只是参数不同
-
// 注意这块不能使用箭头函数 Function.prototype.myApply = function (context) { if (typeof this !== 'function') { return } context = context || window context.fn = this let args = arguments[1] || [] let result = context.fn(args) // 如果是 call 方法就应该这么写,二者只有参数不同 // let args = [...arguments].slice(1) // let result = context.fn(...args) delete context.fn return result }
- new 绑定
- new 一个函数的时候都发生了什么
- new 绑定 this 指向返回的对象
- 优先级
- new > call / apply / bind> 隐式绑定 > 默认
- 注意 new 操作符的优先级最高,所以在我们自己实现bind的时候要注意
- 因为 bind 返回值是一个函数,而这个返回的函数可能被当作构造函数
- 所以在实现 bind 函数的时候有这个步骤
-
Function.prototype.myBind = function(context) { if (typeof this !== 'function') { return } context = context || window let Fn = this let args = [...arguments].slice(1) return function fn() { // 这一步就是因为 new 的优先级高 const target = this instanceof fn ? this : context return Fn.apply(target, [...arguments, ...args]) } }
- new > call / apply / bind> 隐式绑定 > 默认
- 箭头函数的 this 指向箭头函数的声明位置
- 关于箭头函数,详细的请参考这篇文章
示例总结
关于 this 指针的面试题目,很多都是打印结果的,还是看几个例子吧,我还是建议看《你不知道的javascript》上,这本书里面有很多详细的介绍,还有一些关于严格模式的例子
总之记住两句话
- this 取决于函数的执行上下文
- this 的优先级 new > 显式绑定 > 隐式绑定 默认绑定
示例1
function foo() {
console.log(this.a);
}
function doFoo() {
foo();
}
var obj = {
a: 1,
doFoo: doFoo
};
var a = 2;
obj.doFoo()
doFoo()
这道题很简单,打印结果是【2,2】
知识点:隐式绑定丢失
示例2
var a = 10
var obj = {
a: 20,
say: () => {
console.log(this.a)
}
}
obj.say()
var anotherObj = { a: 30 }
obj.say.apply(anotherObj)
打印结果是【10,10】
知识点:箭头函数没有 this 指针、作用域查找
示例3
var obj = {
say: function () {
var f1 = () => {
console.log(this);
}
f1();
},
pro: {
getPro: () => {
console.log(this);
}
}
}
var o = obj.say;
o();
obj.say();
obj.pro.getPro();
打印结果是【window,obj, window】
知识点:箭头函数没有 this 指针、作用域查找、隐式绑定丢失
示例4
function foo(something){
this.a = something
}
var obj1 = {
foo: foo
}
var obj2 = {}
obj1.foo(2);
console.log(obj1.a);
obj1.foo.call(obj2, 3);
console.log(obj2.a);
var bar = new obj1.foo(4)
console.log(obj1.a);
console.log(bar.a);
打印结果是【2,3,2,4】
知识点:显式绑定、new 操作符的优先级