Xen*_*lar 4 javascript foreach bind this
我是Javascript的新手,只是想确保我理解它是如何处理this
关键字的,因为......好吧,它看起来很混乱.我已经在StackOverflow上查看了类似的问题,并希望确保我没有向前推进错误的想法.
所以我正在定义一个类似的类,并希望处理构造函数中收到的每个点.
function Curve(ptList) {
this.pts = [];
if(ptList.length > 2) {
// I want to call "addPoint" for every item in ptList right here
}
}
Curve.prototype.addPoint = function(p) {
this.pts.push(p);
/* some more processing here */
}
Run Code Online (Sandbox Code Playgroud)
所以,最初我以为我可以做到:
ptList.forEach(this.addPoint);
Run Code Online (Sandbox Code Playgroud)
但我不能,因为这仅仅是一个指针传递给所述原型函数,这意味着this
在addPoint
指全局对象.
然后我尝试了:
ptList.forEach(function(p) { this.addPoint(p); });
Run Code Online (Sandbox Code Playgroud)
但我不能,因为this
只要我输入内部函数(它不再引用Curve
正在构造的对象)就引用全局范围,因此addPoint
未定义.
解决这个问题的方法是创建一个变量,该变量引用this
一个范围,我仍然可以在子函数中与之交谈:
var _this = this;
ptList.forEach(function(p) { _this.addPoint(p); });
Run Code Online (Sandbox Code Playgroud)
这最终有效(但对于没有JS经验的人来说看起来很奇怪).但后来我发现了这个bind
函数,它让我不能定义一个简单的函数包装器:
ptList.forEach(this.addPoint.bind(this));
Run Code Online (Sandbox Code Playgroud)
最后,这似乎是最好,最简洁的方法,甚至认为它看起来很傻.没有这个bind
功能,addPoint
就不知道它被调用了哪个对象,没有第一个this
,我甚至找不到我的addPoint
功能.
有没有更好的方法来做这个看似简单的事情,或者推荐的最后一行代码是什么?
该forEach()
方法和其他类似的数组方法一样,map()
并filter()
提供一个thisArg
专门为此目的调用的可选参数.
这作为this
调用函数时提供给函数的"参数":
ptList.forEach(this.addPoint, this);
Run Code Online (Sandbox Code Playgroud)
当这样的参数不可用时,则在使用闭包变量(变量名self
通常用于此)之间进行选择,或者.bind()
主要是偏好问题.请注意,另一个选项是在构造函数中定义函数并捕获闭包中的所有内容:
function Curve(ptList) {
var pts = [];
function addPoint(p) {
pts.push(p);
}
if(ptList.length > 2) {
ptList.forEach(addPoint);
}
this.addPoint = addPoint;
}
Run Code Online (Sandbox Code Playgroud)
这需要比将函数放在原型上更多的内存,因为每个实例都有自己的副本(并且还排除了原型允许你做的一些事情),但Douglas Crockford(JSON和JSLint的发明者)最近说他甚至this
不再使用,理由是内存便宜,但CPU周期不是(遍历原型链需要相当多的处理).