完整系统的掌握this,首先得明白严格模式和非严格模式会影响this指向。
1.在全局执行环境下,无论是否严格模式,this都指向全局对象,比如平时前端开发<script>标签中:
// 在浏览器中, window 对象同时也是全局对象:
console.log(this === window); // true
2.简单调用(this没有被执行环境定义)且非严格模式下,this的值默认指向全局对象:
function f1(){
return this;
}
//在浏览器中:
f1() === window; //在浏览器中,全局对象是window
//在Node中:
f1() === global;
然而在严格模式下,this默认为undefined:
function f2(){
"use strict"; // 严格模式
return this;
}
f2() === undefined; // true
3.通过call,apply和bind可以手动指定方法中this的指向,具体不赘述查阅API即可。
4.ES6的箭头函数可以固化this的指向——this与封闭词法环境的this保持一致,永远被设置为它被创建时的环境。全局环境中,this被设置为全局对象:
var globalObject = this;
var foo = (() => this);
console.log(foo() === globalObject); // true
无论使用什么手段都无法再改变this的指向:
// 接着上面的代码
// 作为对象的一个方法调用
var obj = {foo: foo};
console.log(obj.foo() === globalObject); // true
// 尝试使用call来设定this
console.log(foo.call(obj) === globalObject); // true
// 尝试使用bind来设定this
foo = foo.bind(obj);
console.log(foo() === globalObject); // true
5.作为对象的方法被调用,this指向调用该函数的对象。
6.原型链中的this,仍然指向调用该函数的对象,就像该方法在对象上一样:
var o = {
f: function() {
return this.a + this.b;
}
};
var p = Object.create(o);
p.a = 1;
p.b = 4;
console.log(p.f()); // 5
7.getter与setter中的this,用作getter和setter的函数都会把this绑定到设置或获取属性的对象:
function sum() {
return this.a + this.b + this.c;
}
var o = {
a: 1,
b: 2,
c: 3,
get average() {
return (this.a + this.b + this.c) / 3;
}
};
Object.defineProperty(o, 'sum', {
get: sum, enumerable: true, configurable: true});
console.log(o.average, o.sum); // logs 2, 6
8.当一个函数作为构造函数时,它的this绑定到正在构造的新对象。
9.当函数被用作事件处理函数时,this指向触发事件的元素。
10.当函数作为一个内联事件处理函数时,this指向监听器所在的DOM元素:
<button onclick="alert(this.tagName.toLowerCase());">
Show this
</button>
上面的alert会显示button,注意只有外层代码中的this是这样设置的,如果包裹了一层作用域:
<button onclick="alert((function(){return this})());">
Show inner this
</button>
这种情况下,没有设置内部函数的this,所以按照第二条规则。