1、简介
在 JavaScript 中,this 是一个关键字,它在使用函数调用时自动绑定到合适的对象上。this是在运行时被绑定的,和调用方式以及调用的位置有关系,与定义/编写的位置没有关系。
2、绑定规则
2.1、默认绑定
当独立函数调用(函数没有被绑定到某个对象上进行调用)时,this 默认绑定到全局对象(浏览器环境下为 window 对象,Node.js 环境下为 global 对象)。这种情况下的 this 被称为默认绑定。
- 默认绑定全局对象window
-
全局作用域下独立调用函数,this指向window
// 例1 function test1() { console.log(this); } test1(); // 1、this绑定window // 例2 function test2(func) { func() } var person = { say: function() { console.log(this); } } test2(person.say); // 2、 这是一个独立函数的调用,并没有进行任何的对象绑定,所以this绑定window
2.2、 隐式绑定
当函数作为对象的方法调用时,this 绑定到调用该方法的对象。这种情况下的 this 被称为隐式绑定。
function say() {
console.log(this); // person对象
}
var person = {
name: "person1",
say: say
}
person.say(); // 1、此时函数作为对象的方法调用,此时this指向person对象
var func = person.say;
func(); // 2、此时say最终被调用的位置是func,而func在进行调用时没有绑定任何的对象,也就没有形成隐式绑定,此时this指向window
2.3、显示绑定
通过使用 call()
、apply()
或 bind()
方法,可以显式地绑定 this。这种情况下的 this 被称为显式绑定。
call()
方法调用函数时,将第一个参数作为 this 的绑定对象,后续的参数会作为参数传递给函数,且当第一个参数为null、undefined的时候,默认指向window。
function say() {
console.log(this);
}
say.call({name: "person1"}); // {name: "person1"}
say.call(123); // Number对象
apply()
方法调用函数时,将第一个参数作为 this 的绑定对象,第二个参数是一个数组,数组中的元素作为参数传递给函数,且当第一个参数为null、undefined的时候,默认指向window。
function say(greeting) {
console.log(this);
console.log(greeting + ' ' + this.name);
}
var person = {
name: "person1"
};
say.apply(person, ['Hello']); // 绑定person对象
say.apply(null,['World']); // 绑定window
bind()
方法创建一个新的函数,其 this 值被绑定到传入的对象。bind() 方法返回的是一个函数,需要手动调用以执行。且当第一个参数为null、undefined的时候,默认指向window。
function say() {
console.log(this.name);
}
var person = {
name: "person1"
};
var boundFunction = say.bind(person);
boundFunction();
小结:
- 三种绑定都可以改变函数的this对象指向。
- 三种绑定第一个参数都是this要指向的对象,如果没有这个参数或参数为undefined或null,则默认指向全局window。
- 三种绑定都可以传参,但是apply是数组,而call是参数列表,且apply和call是一次性传入参数,而bind可以分为多次传入。
- bind 是返回绑定this之后的函数,需要手动调用;apply 、call 则是立即执行 。
2.5、 其它
- 箭头函数
箭头函数是 ES6 中的新特性,箭头函数根据外层作用域来决定this。
var person = {
name: "person1",
say: () => {
console.log(this.name); // 此处的 this 指向全局对象,输出 undefined
}
};
person.say();
-
内置函数setTimeout
setTimeout(function() {
console.log(this); // 绑定window
}, 2000);
3、总结
this是在运行时被绑定的,和调用方式以及调用的位置有关系,与定义/编写的位置没有关系。默认绑定会将 this 绑定到全局对象,隐式绑定将 this 绑定到调用方法的对象,显式绑定通过 call()、apply() 和 bind() 方法手动绑定 this。此外,箭头函数根据外层作用域来决定this。