目录
一.前言
this关键字是javascript中最复杂的机制之一,是一个被自动定义在所有函数作用域中的一个很特别的关键字。
1.1为什么要用this关键字?(我们先看下面两端代码)
1.1为什么要用this关键字?(我们先看下面两段代码)
function identify() {
return this.name.toUpperCase();
}
function speak() {
var greeting = "HELLO" + identify.call(this);
console.log("greeting");
}
var me = {
name: "Kyle",
};
var you = {
name: "Reader",
};
identify.call(me);
identify.call(you);
speak.call(me);
speak.call(you);
//该例子只是简单的举例,重在说明this的用处
可以看见这段代码可以在不同的上下文对象(me,you)重复使用函数identify()和speak(),不用针对每个对象编写不同版本的函数
可是,假如我们不使用this,则需要给identify和speak显示传入一个上下文对象(参数)
function identify(context) {
return context.name.toUpperCase();
}
function speak(context) {
var greeting = "HELLO" + identify.call(this);
console.log("greeting");
}
identify(you);
speak(me);
这样子当然可以实现功能,但随着使用模式越来越复杂,代码会变得更加混乱,而this更加简介且易于复用。
1.2.1对this的误解
在彻底认识this之前,我们需要消除一些对this的误解。
误解一:this指向函数自身
问:为什么需要从函数内部引用函数自身呢?
经典案例:
- 递归(比如写一个树形组件的时候)
let data = {
name: '1',
children: [
{
name: '1',
children: [
{
name: '1.1.1'
}
]
},
{
name: '1.2',
children: []
},
{
name: '1.3',
children: []
}
]
}
function renderTreeChildren(node) {
console.log(node.name, node.children);
if (node.children && node.children.lenth) {
node.children.map(item => renderTreeChildren(item))
}
}
renderTreeChildren(data)
// 1 [
// { name: '1', children: [ [Object] ] },
// { name: '1.2', children: [] },
// { name: '1.3', children: [] }
// ]
- 在写第一次被调用后自己解除绑定的事件处理器的时候
let btn = document.getElementById("btn")
btn.onClick=function(){
//.....
btn.onClick=null;
}
以上两个案例都需要用this来指向函数本身。(虽然案例没体现出来),但实际上,这就会给人造成误解,认为this确实是指向函数本身。这是一个误解!
下面这个例子证明this不指向函数本身,需求是记录foo被调用的次数
function foo(num) {
console.log('foo' + num);
//记录foo被调用的次数
this.count++;
}
foo.count = 0
let i
for (let i = 0; i < 10; i++) {
if (i > 5) {
foo(i)
}
}
// foo6
// foo7
// foo8
// foo9
//
// 有四次输出,证明被调用了四次
console.log(foo.count);//0
console.dir(foo);
/**
* console.log()方法可以打印输出结果
而console.dir()方法可以在控制台显示指定javascript对象的属性。打印出该对象的所有属性和属性值.
*/
可以看见,我们在foo函数内部添加了count属性,也通过参数传递证明了函数确确实实被调用了四次,也就是说this.count的值应该是4,但在最后打印foo.count的时候,发现值为0,这说明在函数内部,this.count并不等于foo.count。所以this并未指向foo函数本身。
结论:this并不指向函数本身
1.2.2那么,如果我们确实需要在函数内部引用函数本身,该怎么做?
案例一:有的人会绕过理解this的真正意义和工作原理,通过词法作用域来解决,如下
function foo(num) {
console.log('foo' + num);
//记录foo被调用的次数
data.count++;
}
let data = {
count: 0
}
let i
for (let i = 0; i < 10; i++) {
if (i > 5) {
foo