与其他语言相比,javascript的this关键字略有不同,此外,在严格模式和非严格模式之间也会有一些差别。
在大多数情况下,函数的调用方式决定了this的值,this不能在执行期间赋值,同时在每次函数被调用的时候this的值也可能不同。
参考来源:MDN this关键字
1.全局上下文
无论是否在严格模式下,在全局运行上下文中this都会指向全局对象(即window对象);
在控制台输出直接输入this,按回车,会输出window对象;
在全局环境中定义的对象,都可以直接用window.对象名访问:
console.log(this === window); // true
a = 37;
console.log(window.a); // 37
this.b = "MDN";
console.log(window.b) //"MDN"
console.log(b) //"MDN"
2.函数上下文
在函数内部,this的值取决于函数是如何被调用的,如果是直接调用函数,且在非严格模式下,this会被默认设置为全局对象:
function f1(){
return this;
}
f1() === window; // true
在严格模式下,如果没有被执行的上下文定义,它将会默认为undefined:
function f2(){
"use strict"; // 这里是严格模式
return this;
}
f2() === undefined; // true
3.构造函数中的this
当一个函数作为构造函数来使用(使用new关键字),它的this与即将被创建的新对象绑定,即this指向新生成的实例。当然如果构造器有返回对象,this会指向返回的对象:
function C(){
this.a = 37;
}
var o = new C();
console.log(o.a); // logs 37
function C2(){
this.a = 37; //僵尸代码,不影响代码执行的最终结果
return {a:38};//构造器返回的对象
}
o = new C2(); //this指向返回的对象
console.log(o.a); // logs 38
4.call和apply
调用call()和apply()方法的时候,this会指向指定的对象(第一个参数,如果为空,则默认指向全局对象):
function add(c, d){
return this.a + this.b + c + d;
}
var o = {a:1, b:3};
add.call(o, 5, 7); //this指向O,结果为 1 + 3 + 5 + 7 = 16
add.apply(o, [10, 20]); // 1 + 3 + 10 + 20 = 34
5.bind
ES5中引入了Function.prototype.bind,调用bind()方法会创建一个具有相同函数体和作用域的函数,但是在这个新函数中,this会永久指向bind()函数的第一个参数:
function f(){
return this.a;
}
var g = f.bind({a:"azerty"});
console.log(g()); // azerty
var o = {a:37, f:f, g:g};
console.log(o.f(), o.g()); // 37, azerty
6.DOM事件处理中的this
当函数被用作事件处理器的时候,它的this指向触发时间的元素(一些浏览器在使用非addEventListener的函数动态添加监听函数时不遵守这个约定):
// 被调用时,将关联的元素变成蓝色
function bluify(e){
console.log(this === e.currentTarget); // 总是 true
// 当 currentTarget 和 target 是同一个对象是为 true
console.log(this === e.target);
this.style.backgroundColor = '#A5D9F3';
}
// 获取文档中的所有元素的列表
var elements = document.getElementsByTagName('*');
// 将bluify作为元素的点击监听函数,当元素被点击时,就会变成蓝色
for(var i=0 ; i<elements.length ; i++){
elements[i].addEventListener('click', bluify, false);
}