前言
本文解析了ES5以及ES6的this指向问题。
JavaScript 允许在函数体内部,引用当前环境的其他变量。由于函数可以在不同的运行环境执行,所以需要有一种机制,能够在函数体内部获得当前的运行环境(context)。所以,this就出现了,它的设计目的就是在函数体内部,指代函数当前的运行环境。
1.情况一
包含它的函数作为方法被调用时所属的对象
看仔细了,是:>>>>【包含它的函数】 【作为方法被调用时】 【所属的对象】
function m(){
console.log(this)
}
m();
实际上就是:
function m(){
console.log(this)
}
window.m();// 浏览器环境下
2.情况二
直接调用
直接通过 函数名(…)来对函数进行调用的方式,都称为直接调用。这时函数内部的 this 指向全局对象,在浏览器中全局对象是 window。
3.情况三
构造函数实例化时内部this指向
function M() {
console.log(this);//m
}
var m = new M();
4.情况四
匿名函数的this指向
第一种:第一种是真正意义上的匿名函数,调用者为‘undefind’,但是在不严格条件下指向顶级对象。
示例4-1:
var m = {
mm: function() {
console.log(this); //m
return(function() {
console.log(this); //window,浏览器环境下
})();
}
};
m.mm();
第二种:自执行函数如setInterval()以及setTimeout(),这是因为:这种方法内部的调用执行在与所在的函数分离的上下文环境中。这样,如情况二所示,这会导致这些代码中包含的 this 关键字会指向全局对象!注意,即使在严格情况下也是如此。
示例4-2:
var m = {
mm: setInterval(function M(){
alert(this);// window,浏览器环境下
})
};
m.mm;
题外话:测试第二个示例前最好改一下alert()函数…
另外,想在浏览器测试严格环境下,你需要在测试的代码上形成单独的作用域…
情况五
ES6 的箭头函数的this指向
箭头函数本身是没有this的,从而导致=>>>>>指向最近的上下文作用域中。
注意:箭头函数内部的this指向,在箭头函数定义的时候已经确定了,不会再根据上下文环境动态改变。
示例5-1:
function M(){
this.a = 0;
setInterval(() => {
this.a++;
console.log(this.a);
}, 1000);
}
var m = new M();
注意对比示例【4-2】和【5-2】
示例5-2:
var m = 1;
var M = {
m: 2,
methods: {
m: 3,
c: function () { console.log(this.m) },
c2: () => { console.log(this.m) }
}
}
M.methods.c();// 3
M.methods.c2();// 1
上面示例中,要注意,对象体内部并不构成单独作用域!