参考:
MDN-this
前端基础知识-this部分
JavaScript 的this原理-阮一峰的网络日志
this是执行上下文的一个属性,在执行前的编译时生成的,因此在运行时不能改变this的值。
this的出现是由于函数可能会运行在不同的变量环境中,我们需要有一套机制来获取当前函数的运行环境,在函数内部方法中去调用内部的属性。
一般来说this的指向和它的调用方式有关,每次被调用时this的指向可能都会不同。除此之外,ES6的bind/apply/call函数可以直接指定this的指向对象,箭头函数的this指向它定义时,外层环境中的this,箭头函数的this在定义时就决定了。
具体说this的指向大概有以下几种情况:
- 默认指向全局上下文,也就是在任何函数体之外的直接调用,在非严格模式下this指向window,严格模式下指向undefined。
- 对象调用函数,(函数需要使用function定义,不能是箭头函数),比如
obj.fn()
,this指向调用对象。 - call / bind / apply 方式直接绑定函数的this对象,如foo.call(obj)。
- 箭头函数, this指向的是定义该函数时,外层环境中的this,箭头函数的this在定义时就决定了,不能改变。
- new 关键字把函数作为构造函数使用的情况下,this指向函数返回的对象,如果没有返回对象,则指向新生成的对象。
function C2(){
this.a = 37;
return {a:38}; // return 38;
}
o = new C2();
console.log(o.a);
// o.a=38 // return 38; o.a=37
- 当函数被用作事件处理函数时,它的 this 指向触发事件的元素。
// 被调用时,将关联的元素变成蓝色
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);
}
JavaScript 的this原理——阮一峰
由于函数可以在不同的运行环境执行,所以需要有一种机制,能够在函数体内部获得当前的运行环境。所以,this就出现了,它的设计目的就是在函数体内部,指代函数当前的运行环境。
《浏览器工作原理与实践》
在对象内部的方法中使用对象内部的属性是一个非常普遍的需求。但是 JavaScript 的作用域机制并不支持这一点,基于这个需求,JavaScript 又搞出来另外一套 this 机制。
但是有一个问题出现了,前面我们已经了解到作用域链的生成由代码定义的位置决定,而this又是由调用它的对象决定的,这中间是不是矛盾了呢?
其实这是同一个逻辑链,函数调用,生成执行上下文,得到一个this属性指向当前函数的变量环境,而如果当前变量环境找不到变量,则需要顺着作用域链去寻找外部的变量环境,而外部的作用域链是代码定义时就规定的。