this 是 Javascript语言 的一个保留关键字,它代表函数运行时自动生成的一个内部对象,只能在函数内部使用。首先要记住的是,函数中的
本章内容:
在开始今天的内容之前,先来看看下面的代码:
1. 谁调用,谁负责
来回顾一下 实例1:
而接下来的
在
注: 匿名函数内的
结论: 谁调用,谁负责。
2. new的过程
new Test2() 其实执行了三步动作:
当没有显式返回值或者返回为基本类型、null时,默认将
搞清楚new的过程,相信你对打印出
结论: 当使用new时,函数内部的this指向已经改变了,并不指向window。
3. 怪异的return
在上面的“new的过程”中,我们了解了new的函数内的this指向,但是,也有一些例外,比如下面:
结论: 如果return的是一个对象(null除外),那么this指向的这个对象,否则this依旧指向实例对象。
4. 被干掉的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();
}
保存着你的答案,接下来我们一一分析。1. 谁调用,谁负责
来回顾一下 实例1:
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的,更准确的说是指向调用者。结论: 谁调用,谁负责。
2. new的过程
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的过程。new Test2() 其实执行了三步动作:
var obj = {};
obj.__proto__ = Test2.prototype;
Test2.call(obj);
首先,创建了一个空对象obj接着,将这个空对象的[[Prototype]](__proto__)成员指向了Test2函数对象prototype成员对象最后,将Test2函数对象的this指针替换成obj。当没有显式返回值或者返回为基本类型、null时,默认将
this 返回。可参考:3. 怪异的return搞清楚new的过程,相信你对打印出
c的原因已经明白了。结论: 当使用new时,函数内部的this指向已经改变了,并不指向window。
3. 怪异的return
在上面的“new的过程”中,我们了解了new的函数内的this指向,但是,也有一些例外,比如下面:
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同样被干掉了,但是它有点不一样,它可以盗用它最接近一层作用域内的 this5. 丢失的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,需要翻墙
!