默认绑定
1. 全局环境下,this 指向 window
console.log(this);
2. 函数独立调用,this 也指向 window
function fn() {
console.log(this);
}
fn(); // 相当于 window.fn()
3. 被嵌套的函数独立调用时,this 也指向 window
let obj = {
a: 2,
foo: function () {
function test() {
console.log(this);
}
test();
},
};
obj.foo(); // foo() 中的 this 指向为 obj,但此处输出仍然为 window,因为 test() 相当于独立调用。
// 如何在 test 中拿到 obj 中的 a ?
let obj = {
a: 2,
foo: function () {
let that = this;
function test() {
console.log(that.a);
}
test();
},
};
obj.foo();
4. IIFE(自执行函数中内部的 this 也指向 window)
// 情况一
(function () {
console.log(this);
})();
// 输出 window
// 情况二
function foo() {
(function test() {
console.log(this);
})();
}
let obj = {
a: 2,
foo: foo,
};
obj.foo();
// 输出 window
// 如何在 test 中拿到 obj 中的 a ?
function foo() {
(function test(that) {
console.log(that);
})(this);
}
let obj = {
a: 2,
foo: foo,
};
obj.foo();
5. 闭包中的 this 仍然指向 window
let obj = {
a: 2,
foo: function () {
return function test() {
console.log(this);
};
},
};
let result = obj.foo();
result();
// 输出 window
// 如何在 test 中拿到 obj 中的 a ?
let obj = {
a: 2,
foo: function () {
let _this = this;
return function test() {
console.log(_this.a);
};
},
};
let result = obj.foo();
result();
隐式绑定
把对象当做方法来调用,this 指向调用者
function foo() {
console.log(this);
}
let obj1 = {
a: 1,
foo: foo,
obj2: {
a: 2,
foo: foo,
},
};
obj1.foo(); // 输出 obj1
obj1.obj2.foo(); // 输出 obj2
隐式丢失
以下几种情况会造成隐式丢失
1. 函数别名
function foo() {
console.log(this);
}
let obj = {
a: 1,
foo: foo,
};
let bar = obj.foo;
bar(); // 输出 window
2. 参数传递
var _this = "window";
function foo() {
console.log(this._this);
}
function bar(fn) {
fn();
}
let obj = {
_this: "obj",
foo: foo,
};
bar(obj.foo); // 输出 window
3. 内置函数
此类情况主要出现在 setTimeout 和 setInterval 中,类似于 “参数传递” 的情况。
setTimeout(function () {
console.log(this);
}, 1000);
4. 间接调用
- 隐式绑定,函数当做对象中的方法来使用,内部的 this 指向了该对象
obj.foo(); // 输出 3 - 将 obj.foo 函数对象赋值给 p.foo 函数,然后立即执行。相当于仅仅是 foo() 函数的立即调用,内部的 this 默认指向了 window
(p.foo = obj.foo)(); // 输出 2 - 将 obj.foo 赋值给 p.foo 函数,之后 p.foo() 函数再执行,其实是属于 p 对象的方法的指向,this 指向了当前的 p 对象
p.foo = obj.foo; p.foo(); // 输出 4
5. 其他情况(以下几种情况,this 都指向 window)
var a = 0;
var obj = {
a: 1,
foo: foo,
};
function foo() {
console.log(this.a);
}
(obj.foo = obj.foo)(); // 输出 0
(false || obj.foo)(); // 输出 0
(1, obj.foo)(); // 输出 0
显式绑定
-
call(),apply(),bind()把对象绑定到 this 上,叫做显式绑定var a = 0; function foo() { console.log(this.a); } var obj = { a: 2, }; foo(); // 输出 0 foo.call(obj); // 输出 2 foo.apply(obj); // 输出 2 foo.bind(obj)(); // 输出 2 -
硬绑定,显式绑定的一个变种,使得 this 不能再被改变
var a = 0; function foo() { console.log(this.a); } var obj = { a: 2, }; var bar = function () { foo.call(obj); }; bar(); // 输出 2 setTimeout(bar, 2000); // 输出 2 bar.call(window); // 输出 2 -
在
forEach()、map()、filter()、some()、every()等一些内置函数中,在第二个形参的位置可以传入一个对象,改变回调函数中 this 的指向为该对象var _this = "window"; var obj = { _this: "obj", }; var arr = [1, 2, 3]; arr.forEach(function (el, index) { console.log(el, index, this); }, obj);
new 绑定
如果是 new 关键字来真实性函数,相当于构造函数来实例化对象,那么内部的 this 指向了当前实例化的对象
function fn() {
console.log(this);
return;
}
var f1 = new fn(); // 输出 fn
function fn2() {
console.log(this);
return {
name: "fn2",
};
}
var f2 = new fn2(); // 输出 fn2
严格模式下 this 的指向
-
独立调用的函数内部的 this 指向
undefinedfunction foo() { "use strict"; console.log(this); } foo(); // 输出 undefined -
函数
apply()和call()内部的 this 始终是它们的第一个参数var color = "red"; function showColor() { "use strict"; console.log(this); console.log(this.color); } showColor.call(undefined); // 输出 undefined