再来摸摸Javascript中this的坑
this
并不是在创建时确定下来的,而是在函数执行的时候才确定的。这个也是造成使用this
时出现很多误解的原因。- 谁调用,谁负责
- new的过程
- 怪异的return
- 被干掉的this
- 丢失的this
// 实例1
var name = 'a';
var obj = {
name: 'b',
getName: function() {
console.log(this.name);
}
};
obj.getName();
var getName = obj.getName;
getName();
var obj2 = (function() {
return function() {
console.log(this.name);
}
})();
obj2();
// 实例2
function Test() {
console.log(this.name);
}
Test();
var test = new Test();
function Test2() {
this.name = 'c';
}
var test2 = new Test2();
console.log(test2.name);
// 实例3
function Test3() {
this.name = 'd';
return {}; // 1 | 'd' | null | undefined
}
var test3 = new Test3();
console.log(test3.name);
function Test4() {
this.name = 'd';
return 1;
}
var test4 = new Test4();
console.log(test4.name);
// 实例4
function Test5() {
"use strict";
console.log(this.name);
}
console.log(Test5());
function test6() {
console.log(this.name);
}
// 实例5
var btn = document.querySelector('.btn');
btn.name = 'button';
btn.onclick = test6;
var btn2 = document.querySelector('.btn2');
btn2.name = 'button';
btn2.onclick = function() {
test6();
}
var name = 'a';
var obj = {
name: 'b',
getName: function() {
console.log(this.name);
}
};
obj.getName(); // b
var getName = obj.getName;
getName(); // a
var obj2 = (function() {
return function() {
console.log(this.name);
}
})();
obj2(); // a
obj.getName()
,它打印的是b,为什么呢?因为调用getName()
的是obj
这家伙,自然,它的this
就指向了obj
,所以this.name
自然就是b。getName()
为毛打印的是a
呢?因为当前调用getName()
的并不是obj了,而是全局变量window
,所以打印结果是a
。obj2
中,我们采用了立即执行函数,它返回一个函数,而当我们调用时,调用它的也是全局变量window
,所以其打印的结果也是a。this
是指向window
的,更准确的说是指向调用者。function Test() {
console.log(this.name);
}
Test(); // a
var test = new Test(); // undefined
function Test2() {
this.name = 'c';
}
var test2 = new Test2();
console.log(test2.name); // c
c
,就有必要了解new的过程。var obj = {};
obj.__proto__ = Test2.prototype;
Test2.call(obj);
[[Prototype]](__proto__)
成员指向了Test2
函数对象prototype
成员对象Test2
函数对象的this
指针替换成obj
。this
返回。可参考:3. 怪异的returnc
的原因已经明白了。function Test3() {
this.name = 'd';
return {};
}
var test3 = new Test3();
console.log(test3.name); // undefined
function Test4() {
this.name = 'd';
return 1;
}
var test4 = new Test4();
console.log(test4.name); // d
可以再试试return 'd' | null | undefined
中的一个或更多类型。
结论: 如果return的是一个对象(null除外),那么this指向的这个对象,否则this依旧指向实例对象。
4. 被干掉的this
function Test5() {
"use strict";
console.log(this.name);
}
console.log(Test5()); // Uncaught TypeError: Cannot read property 'name' of undefined
在严格模式下,函数内的this
都指向了undefined
。
除了严格模式下,函数内的this
被干掉了。在ES6中箭头函数的this
同样被干掉了,但是它有点不一样,它可以盗用它最接近一层作用域内的 this
5. 丢失的this
function test6() {
console.log(this.name);
}
var btn = document.querySelector('.btn');
btn.name = 'button';
btn.onclick = test6; // button
var btn2 = document.querySelector('.btn2');
btn2.name = 'button';
btn2.onclick = function() {
test6(); // a
}
在JavaScript中,事件绑定的函数的this
是指向绑定元素的,比如上面的onclick绑定的test6函数内的this是指向btn元素的。而btn2绑定事件为什么打印a呢?回顾一下上面第一节中提到的“谁调用,谁负责”。
此外,setTimeout
和setInterval
等函数内this
默认的指向是Window。
如有疑问,欢迎在下方的评论区留言!
备注:评论插件已经换成Disqus,需要翻墙 !