浅析javascript中的this关键字

时间:2021-07-18 19:16:16

与其他语言相比,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);
}