共计 2285 个字符,预计需要花费 6 分钟才能阅读完成。
JS 中的 this
到底是什么
如果没有零碎理解过,可能 JavaScript 中的 this 始终是个迷。
可能你在 Vue
中见过有数这样相似 const that = this;
的表达式
const that = this;
const obj = {
message: "I'm obj.",
printThis: function(){console.log(this);
},
printThat: function(){console.log(that);
},
};
obj.printThis();
obj.printThat();
这里为什么肯定要应用 const that = this;
呢能力拿到正确的 this
呢?
是这样的,对于函数(也就是个对象)中的 this
,指向的是 调用该函数的对象 的。
举个????
function printThis(){console.log(this);
}
const obj = {
message: "I'm obj.",
printThis: printThis
}
printThis(); // 等同于 this.printThis(); 都是在 window 这个上下文下调用 this 指向的是调用函数的对象: window
obj.printThis(); // 这个 printThis 是在 obj 的上下文下调用 this 指向的是调用函数的对象: obj
所以能够做个小总结: this
总是指向调用本函数(对象)的对象。
而在在构造函数内的 this
是指向哪里的呢?指向的也是 调用构造函数的对象 吗?
构造函数会在对象被实例化的时候被调用,会调用 call()
这个办法来指向该对象,故 this
指向的是 对象自身 。具体细节可自行查阅new
一个对象的时候做了些什么。
所以就能够回到开始的问题了,为什么要用 const that = this;
呢?
const that = this;
const obj = {
message: "I'm obj.",
printThis: function(){console.log(this);
},
printThat: function(){console.log(that);
},
};
obj.printThis();
obj.printThat();
其实也就是为了将内部的 this 保留到 that,而后在函数中调用内部的 this。
一句话:this
就是调用本函数(对象)的对象。
JS 中如何优雅的应用 this
综合上述,想必应该大略理解了 this 是什么了。应用 const that = this;
这种语句必定不优雅,那么在我的项目中如何优雅的来应用 this 呢?
箭头函数
首先能够通过箭头函数来间接应用 this,因为箭头函数是 不会绑定指针域 的,也就是说箭头函数内的 this
和箭头函数外层的 this
是一样的。
console.log(this); // 1 这里指向 window
const obj = {
message: "I'm obj.",
printThis: function(){console.log(this);
},
printThisWithArrowFunction: () => { console.log(this); }
}
obj.printThis(); // 2 这里指向 obj
obj.printThisWithArrowFunction(); // 3 这里和 1 一样指向 window
所以能够通过箭头函数来很欢快的解决 this 指向不同问题。
手动扭转函数的this
JS 中函数提供了三个办法来手动设定 this
的指向:call()
、apply()
和bind()
。
通过调用这三个办法来间接调用函数就能够间接指定 this
,那为什么就指定this
须要三个办法呢?
| 办法 | 参数 | 返回值 | 阐明
| call() | this, param1, param2, … | undefined | 传入 this 指向和参数即可调用
| apply() | this,[param1, param2, …] | undefined | 传入 this 指向和 数组形参数 即可调用
| bind() | this, param1, param2, … | Function | 传入 this 指向和参数 返回对应指向的函数
很容易能够发现,三个函数的作用简直是一样的,然而用法上稍有不同,举个????:
function printThis(a, b){console.log(this, a, b);
}
const obj = {message: "I'm obj."}
[printThis.call](http://printthis.call/)(obj, 1, 2);
printThis.apply(obj, [1, 2]); // 数组模式
printThis.bind(obj, 1, 2)(); // 留神返回的是函数,还须要调用下返回值
更多
想必到当初应该对如何正当应用 this
大略了解了吧?那么有什么用途呢?
这里拿大家都晓得的数组裁剪举个????:
const arr = [1, 2, 3];
arr.slice(1); // 去除第一个 这里的 slice 外部的 this 就指向的是 arr!
console.log(arr); // [2, 3]
// 那么如何利用这个个性来将非个别数组类型切割呢?
const obj = {
0: 1,
1: 2,
2: 3,
length: 3 // 肯定要有 length 属性
};
// 间接调用 obj.slice(1); 是不能够的因为对象的 prototype 没有这个办法
// 能够通过人为扭转 slice 的 this 指针来实现
console.log([Array.prototype.slice.call](http://array.prototype.slice.call/)(obj)); // 应用 call 办法将 this 指向了 obj 即可