bind、call、apply

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
//相同点:三者都是用来改变this指向的
var name = '小王',age=17;
var obj = {
name:'小张',
objAge:this.age,
myFun:function(){
console.log(this.name+"年龄"+this.age);
}
}
var db={
name:'德玛',
age:99
}
obj.myFun.call(db); //德玛年龄99
//注意下面这个括号
obj.myFun.bind(db)(); //德玛年龄99
obj.myFun.apply(db); //德玛年龄99
//不同点:传参
var name = '小王',age=17;
var obj = {
name:'小张',
objAge:this.age,
myFun:function(fm,to){
console.log(this.name+"年龄"+this.age+"来自"+fm+"去往"+to);
}
}
var db={
name:'德玛',
age:99
}
obj.myFun.call(db,'成都','上海');//德玛年龄99来自成都去往上海
obj.myFun.call(db,['成都','上海']);//德玛年龄99来自成都,上海去往undefined
obj.myFun.apply(db,['成都','上海']);//德玛年龄99来自成都去往上海
obj.myFun.bind(db,'成都','上海')();//德玛年龄99来自成都去往上海
obj.myFun.bind(db)('成都','上海');//德玛年龄99来自成都去往上海
obj.myFun.bind(db,['成都','上海'])();//德玛年龄99来自成都,上海去往undefined

//由此可见,apply能够传递一个数组参数,而其他的两个不行
//另外,bind可以在调用的时候再传参

this指向判定

需要找到这个函数的直接调用位置,找到之后就可以根据下面的规则来判定:

  • 由new调用?绑定到新创建的对象
  • 由call或者apply(或者bind)调用?绑定到指定的对象
  • 由上下文对象调用?绑定到那个上下文对象
  • 默认:严格模式下绑定到undefined,否则绑定到全局对象

有些调用可能在无意中使用默认绑定规则。如果想更安全地忽略this绑定,可以使用一个DMZ对象

1
Object.create(null)//不会创建Object.prototype这个委托,比{}更空

箭头函数不会使用上述四条规则,而是会继承外层函数调用的this绑定,且不能被修改


bind、call、apply
https://blog-theta-ten.vercel.app/2021/06/11/bind、call、apply/
作者
Chen
发布于
2021年6月11日
许可协议