默认绑定
当我们不带任何修饰地调用一个函数时,就应用默认绑定的规则
function f(){
var a=2
console.log(this.a)
}
var a=4
f()// 输出4
调用foo时,前面没有任何修饰,因此,f函数的调用位置是全局环境,this.a被解析成了全局变量a
隐式绑定
如果函数在调用时,被另一个函数或对象"引用"了,隐式绑定规则会将this绑定到上一层的对象中
function f(){
console.log(this.a)
}
var obj = {
a: 20,
f:f
}
var a = 3
obj.f() //输出20
f在执行的时候,是被obj调用的,因此this指向对象obj
要注意的是:
对象属性引用链只在上一层的调用位置中起作用
function f(){
console.log(this.a)
}
var obj2 = {
a: 40,
f:f
}
var obj1 = {
a: 20,
obj2:obj2
}
var a = 3
obj1.obj2.f() //输出40
f在执行的时候,最后是被obj2调用的,因此this指向对象obj2
显式绑定
1、call
call方法可以指定函数内部this的指向
function f(){
console.log(this.a)
}
var obj = {
a: 20
}
var a = 3
f.call(obj) //输出20
在上面这段代码中,调用 f 时,call方法将this绑定到obj对象中,使得this.a被解析成obj.a
call方法可以接收多个参数,第一个参数是this所指向的对象,后面的参数则是原函数调用时所需的参数
2、apply
apply方法的作用与call方法类似
唯一的区别是,它接收一个数组作为函数执行时的参数
function f(a,b,c){
console.log(a*b*c + this.d)
}
var obj = {
d: 10
}
f.apply(obj,[1,2,3])
数组中的成员依次作为参数,传入原函数中
apply方法的更多应用,可以参考这篇教程
3、bind
bind方法用于将函数体内的this绑定到某个对象,然后返回一个新函数
var counter = {
count: 0,
f: function () {
this.count++;
}
};
counter.f.bind(counter)
console.log(counter.count)
// 输出0
因为bind方法会返回一个新的函数,因此上面这段代码实际上并没有执行counter的f函数,正确的写法如下:
var counter = {
count: 0,
f: function () {
this.count++;
}
};
counter.f.bind(counter)()
console.log(counter.count)// 输出1
当然,我们也可以将返回的函数赋值给另一个变量
var counter = {
count: 0,
f: function () {
this.count++;
}
};
var newF = counter.f.bind(counter)
newF()
console.log(counter.count)
// 输出1
令this指向别的对象
var counter = {
count: 0,
f: function () {
this.count++;
}
};
var another = {
count:10
}
var newF = counter.f.bind(another)
newF()
console.log(counter.count)//输出0
console.log(another.count)//输出11
此时,执行函数newF时,this指向的是对象another