全局函数 对象方法
this指向当前调用该方法最近的对象(在全局环境即是window或global对象,亦符合此原则)(即动态作用域)
function f(){
console.log(this)
}
f() // window
var o = {
f: function() {
console.log(this)
}
};
o.f(); //o
var f = o.f;
f(); //window
o = {};
f = function() {
console.log(this)
}
o.f = f;
o.f(); // o
o.obj = {
func: f
};
o.obj.func() // o.obj
构造函数
this指向被构造函数创建的实例对象。
构造函数通常不会手动设置返回值,这样在调用构造函数时会默认返回一个this引用的实例对象,如果手动设置了返回值且该返回值不是一个对象时会返回this。
function O(){
this.f = function(){
console.log(this);
}
}
var obj = new O();
obj.f() // obj
call apply
当一个函数通过call/apply调用时,该函数的this指向call/apply的第一个参数对象, 如果第一个参数不是对象,JS会尝试将其转换成对象并指向它。
function func(){
console.log(this.a + this.b)
}
var obj = {a:1, b:2};
func.call(obj); // 3
function printThis() {
console.log(this);
}
printThis.call(1); // Number {[[PrimitiveValue]]: 1}
printThis.call('str'); // String {0: "s", 1: "t", 2: "r", length: 3, [[PrimitiveValue]]: "str"}
ES5 Function.prototype.bind
ES5新增Function.prototype.bind方法接受一个对象参数,返回一个与Function相同但this指向传入的参数对象的新函数。
这个返回的新函数无论在什么情况下被调用this始终指向bind方法第一个参数对象。
Function.prototype.bind不会改变原函数的this指向。
function func1(){
return this.a;
}
var func2 = func1.bind({a:1});
console.log(func2()); // 1
var obj = {a:2, func1:func1, func2:func2};
console.log(obj.func1(), obj.func2()); // 2, 1
DOM事件和内联事件
当函数被当做DOM事件的监听处理函数时, 其 this 指向触发该事件的元素。
<button id="btn">click</button>
document.getElementById('btn').addEventListener('click',function(){console.log(this)});
当函数被当做内联事件的监听处理函数时,其 this 指向window对象,如果内联事件不绑定函数,直接在内联标签中调用this,则this指向触发该事件的元素。
<button onclick="console.log(this)">click1</button> <!--this指向button元素-->
<button onclick="printThis()">click2</button> <!--this指向window对象-->
function printThis(){
console.log(this)
}
总结:在非箭头函数下, this 指向调用其所在函数的对象,并遵循就近原则(适用于 对象,原型链, getter / setter等),函数内部定义新函数this指向window对象(使用函数体内定义命名函数和匿名函数,包括settimeout ,setInterval的回调函数等);构造函数下,this指向被创建实例对象;DOM事件,this指向触发事件的元素。