this是使用JavaScript开发过程中,一个很常见的基础知识点,但同时也是一个很容易出现混淆的点。作为这样一个高频、且基础的知识点,做一次总结,就显得尤为重要。
与其他语言索引,函数的
this关键字在JavaScript中的表现略有不同,变量,在严格模式和非严格模式之间也会有一些区别。在绝大多数情况下,函数的调用方式决定了this的值(运行时绑定)。this不能在执行期间被赋值,并且在每次函数被调用时this的值也可能会不同。ES5引入了bind方法来设置函数的this值,而不用考虑函数如何被调用的。ES2015了引入箭头函数,箭头函数不提供自身的this绑定(this的值将保持为闭合词法上下文的值)。
这是MDN对于this的简单介绍。从这个介绍中,我们可以总结出关于this的几个重点。
- 严格模式与非严格模式,
this的指向是有区别的; this是在函数运行时才绑定;- 我们可以通过一些方法来设置函数的
this值; - 箭头函数不提供自身的
this绑定。 下面我们来通过一些例子,了解下this的这些关键特性
全局上下文
无论严格模式还是非严格模式,在全局执行环境中this都是指向全局对象的。这个全局对象在浏览器中,通常是window;在Node环境中,则是globalThis。
a = 37;
console.log(this.a) //37
函数上下文
在函数里,this的值取决于调用方式。且严格模式与非严格模式有所区别。
function f1() {
return this;
}
//非严格模式
f1() === window; //true
function f1() {
"use strict";
return this;
}
//严格模式
f1() === undefined; //true
绑定this的方法
ECMA5引入Function.prototype.bind()、Function.prototype.call()和Function.prototype.apply()他们都是完成对this的绑定。
bind()
function f(){
return this.a;
}
var g = f.bind({a:"xiaobai"});
console.log(g()); // xiaobai
var h = g.bind({a:'xiaohei'});
console.log(h()); // xiaobai
bind()将this永久绑定至它的第一个参数上。
apply()
var a = {
user:"xiaobai",
fn:function(e,ee){
console.log(this.user);
console.log(e+ee);
}
}
var b = a.fn;
var arr = [500,20];
b.apply(a,arr);//xiaobai 520
apply()可以将this的绑定到第一个参数上,同时可以接收多个参数,作为实参传进去,但它的参数只能为数组。
call()
var a = {
user:"xiaobai",
fn:function(e,ee){
console.log(this.user);
console.log(e+ee);
}
}
var b = a.fn;
b.call(a,1,2); //xiaobai 3
call()可以将this的绑定到第一个参数上,同时可以接收多个参数,作为实参传进去。
箭头函数
在箭头函数中,this与封闭词法环境的this保持一致。在全局代码中,它将被设置为全局对象。
var obj = {
bar: function() {
var x = (() => this);
return x;
}
};
var fn = obj.bar();
console.log(fn() === obj); // true
var fn2 = obj.bar;
console.log(fn2()() === window); // true
当我们调用obj时,此时this绑定了它外部的词法作用域,也就是也obj上,所以fn() === obj;
当直接引用obj时,此时的this则是绑定了仍是它外部的词法作用域,但这时变成了window,所以fn2()() === window.
关于new
前面已经将this的一些基本用法介绍完了,但仍存在一个特性,就是在构造函数中,使用new关键字生成实例时,此时的this时如何绑定的呢?
function Fn1(){
this.a = 37;
}
var o = new Fn1();
console.log(o.a); // 37
function Fn2(){
this.a = 37;
return {a:38};
}
o = new Fn2();
console.log(o.a); // 38
当一个函数用作构造函数时(使用new关键字),它的this被绑定到正在构造的新对象。但如果函数具有返回对象的return语句,则该对象将是 new 表达式的结果。否则,表达式的结果是当前绑定到 this 的对象。
结语
至此,关于this的基本用法也就介绍完毕了,总结一句话:this永远指向的是最后调用它的对象,也就是看它执行的时候是谁调用,但其中的也有一些特殊情况,需要我们格外注意。如文章内有错误,欢迎指正。