this的值取决于函数的调用方式,而不是在哪里定义或创建的。
1.全局上下文
- 在全局执行上下文中(任何函数体外部),this指向全局对象。在浏览器中,全局对象是window。
console.log(this === window); // 在浏览器中为 true
this.a = 37;
console.log(window.a); // 37
2.函数上下文
简单调用
- 当一个函数不是作为一个对象的方法调用的时候,this指向全局对象(严格模式下,this将保持其原始的undefined值)。
function f1(){
return this;
}
// 在非严格模式下
console.log(f1() === window); // true
// 在严格模式下
function f2(){
'use strict'; // 可见这里开启了严格模式
return this;
}
console.log(f2() === undefined); // true
作为对象方法的调用
- 当函数作为对象里的方法被调用时,this指向该对象。
const object = {
method: function() {
return this;
}
};
console.log(object.method() === object); // true
ES6箭头函数
- ES6箭头函数没有自己的this值,箭头函数内的this值继承自外围最近一层非箭头函数的this。
const object = {
method: function() {
return () => this;
}
};
const arrowFunction = object.method();
console.log(arrowFunction() === object); // true
3.构造函数上下文
- 当函数作为构造函数使用(使用new关键字)时,this指向新创建的对象。
function MyConstructor(){
this.a = 37;
}
const obj = new MyConstructor();
console.log(obj.a); // 37
4.使用apply、call和bind
JavaScript 提供了apply、call和bind方法来明确设置函数执行时的this值。
- call和apply在调用函数时立即执行,call接受一个参数列表,apply接受一个参数数组。
- bind返回一个新的函数,允许传入一个参数数组,并允许延迟执行。
function greet() {
return this.name;
}
const person = { name: 'Alex' };
console.log(greet.call(person)); // Alex
console.log(greet.apply(person)); // Alex
const boundGreet = greet.bind(person);
console.log(boundGreet()); // Alex
5.测试
- 指出下面代码的输出
var o = {
f1: function () {
console.log(this);
var f2 = function () {
console.log(this);
}();
}
}
o.f1()
当调用o.f1()时:
由于f1是作为对象o的方法被调用的,因此在f1方法中的this关键字指向o对象。因此,第一个console.log(this);在f1中打印出的是对象o。
接下来,我们定义了一个内部函数f2,并立即执行它。在f2的定义内部,我们同样打印出this的值。
重要的是要记住,普通函数(非箭头函数)的this指向是由其调用方式决定的,而不是由其在哪里定义或创建决定的。在这个例子中,f2作为一个普通函数被立即调用,它并不是作为某个对象的方法被调用的,也没有使用bind、call或apply来明确绑定this。
在非严格模式下,这意味着f2内部的this将指向全局对象(在浏览器中是window对象)。如果此代码在严格模式(使用’use strict’;)下运行,f2内的this将是undefined。