1 前言:
this
是javascript中一个重要的关键词 根据函数执行
时候上下文的不同this
代表的含义也不同
2 为什么使用this
this
提供了优雅的方式来隐式的传递一个对象的引用
this
是在运行时候绑定的,并不是在编写的时候绑定的,它的上下文取决于函数调用时的条件。
this绑定规则有4种
3 绑定机制
3.1 不带任何修饰的函数调用 -默认绑定
没有任何修饰,即没有使用apply/call,也没有显式的对象包含 比如 object.somefunction()
1 | a = 1 |
3.2 隐式绑定
被对象拥有或者包含时候使用隐式绑定,this指向调用对象
1 | let a = 2 |
但此时需要注意一种隐式丢失的情况
1 | let a = 2 |
对象属性引用链中只有最后一条会影响调用1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
function foo(){
console.log(this.a)
}
let obj2 = {
a:42,
foo:foo
}
let obj1 = {
a:2,
obj2:obj2
}
obj1.obj2.foo()//42
3.3 显示绑定
使用call
/apply
/bind
进行硬绑定1
2
3
4
5
6
7
8
9
10
11
12function foo(){
console.log(this.a)
}
obj={
a:1
}
foo.call(obj) // 1
foo.apply(obj) // 1
let foo_with_obj = foo.bind(obj)
foo_with_obj()//1
3.4 new关键词绑定
new的执行过程
1 创建一个全新的对象
2 绑定原型链
3 新对象绑定到函数调用的this
4 函数没有返回其他对象,那么返回新对象
可以看到第3步中,new关键词,会将新对象绑定到调用函数的this上
4 绑定的优先级
new > 显示 > 隐式 > 默认
证明 显式 > 隐式
1 | function foo(){ |
证明 new优先级高于显示绑定1
2
3
4
5
6
7
8
9
10
11
12function foo(something){
this.a= something
}
let obj = {}
let bar = foo.bind(obj)
bar(2)
console.log(obj.a)//2
let baz = new bar(3)
console.log(obj.a)//2
console.log(baz.a)//3
5 apply/call/bind 使用 null作为绑定对象
此时为默认绑定
如果你的函数不会修改this,那么可以放心传入
否则,你的函数会在全局对象上产生可怕的修改1
2
3
4
5
6
7
8
9
10function foo(x){
this.x = x
}
let obj = {}
foo.apply(obj, [2])
console.log(obj.x)//2
foo.apply(null, [3])
console.log(global.x)// 2 3
5.1 避免不必要的默认绑定
可以使用一个空的DMZ对象进行绑定1
2
3
4
5function foo(){
this.a = 1
}
valet SPECIAL_OBJ = Object.create(null)//空对象{}
foo.call(SPECIAL_OBJ)