隐式绑定
当一个函数a保存成某个对象A的属性时,我们称这个函数a为该对象的方法a。当这个方法a被调用时,方法a内部的this指向该方法所属的对象A。
总结一下就是,当一个函数以'方法调用模式'被调用时,this指向直接对象。
var a = 0;
function fn(){
console.log(this.a);
}
var obj = {
a: 1,
myFn: fn,
obj2: {
a: 2,
myFn: fn
}
}
// 这里fn的直接对象是obj,this.a指向obj下的属性a
obj.myFn(); // 1
// 这里fn的直接对象是obj2,this.a指向obj2下的属性a
obj.obj2.myFn(); // 2
隐式丢失
被隐式绑定的函数由于某些原因丢失了绑定对象,this指向改变
原因1:函数别名
把一个隐式绑定的函数赋给了另一个变量,对这个变量进行操作造成隐式丢失,this指向window
var a = 0;
function fn(){
console.log(this.a);
}
var obj = {
a: 1,
myFn: fn
}
// 隐式绑定,this.a指向直接对象obj下的属性a
obj.myFn(); // 1
//obj.myFn被赋值给bar,相当于把console.log(this.a);这句语句赋值给bar,bar与obj没有直接关系
var bar = obj.myFn;
// bar()相当于单纯的执行打印a这个操作,bar的作用域是全局,那么this就是window
// 隐式丢失,this.a指向window下的变量a
bar(); // 0
原因2:参数传递
把一个隐式绑定的函数作为参数传入另一个函数中,在另一个函数内部被调用时造成隐式丢失,this指向window
var a = 0;
function foo(){
console.log(this.a);
}
function bar(fn){
fn();
}
var obj = {
a: 1,
myFn: foo
}
// obj.myFn作为参数传入到bar函数中,在该函数内被调用,相当于在bar函数内部调用了foo(),与obj无关
// 隐式丢失,this.a指向window下的变量a
bar(obj.myFn); // 0
原因3:内置函数
如内置函数setTimeout和setInterval,它俩的第一个参数是回调函数,这个回调函数中this指向window
setTimeout(function(){
console.log(this); // window
});
var a = 0;
function fn(){
console.log(this.a);
}
var obj = {
a: 1,
myFn: fn
}
// obj.myFn作为内置函数setTimeout的回调函数,内置函数执行时造成隐式丢失,this.a指向window下的变量a
setTimeout(obj.myFn,1000); // 0;
原因4:间接调用
将一个隐式绑定的函数用call(),apply()等方法间接调用时,造成隐式丢失,this指向call、apply中首个参数,若为空则指向window
var a = 0;
function fn(){
console.log(this.a);
}
var obj = {
a: 1,
myFn: fn
}
var p = {
a: 2
}
fn.call(); // 0
fn.call(obj); // 1
p.myFn = obj.myFn;
fn.call(p); // 2
其他原因
比如,自执行函数中this指向window
var a = 0;
function fn(){
console.log(this.a);
}
var obj = {
a: 1,
myFn: fn
}
var p = {
a: 2
}
// 相当于fn函数的立即调用,this指向window
(p.myFn = obj.myFn)()