在 forEach 中调用类函数:Javascript 如何处理“this”关键字

2024-04-16

我是 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 */ 
}

所以,最初我想我可以这样做:

ptList.forEach(this.addPoint);

但我不能,因为这只是传递一个指向原型函数的指针,这意味着this in addPoint指的是全局对象。

然后我尝试:

ptList.forEach(function(p) { this.addPoint(p); });

但我不能,因为this一旦我进入该内部函数,就指的是全局范围(它不再指的是Curve正在构造的对象),所以addPoint未定义。

解决这个问题的方法是创建一个引用的变量this在我仍然可以在子功能中交谈的范围内:

var _this = this;
ptList.forEach(function(p) { _this.addPoint(p); });

这最终起作用了(但对于没有 JS 经验的人来说看起来真的很奇怪)。但后来我发现bind函数,这让我不能定义一个简单的函数包装器:

ptList.forEach(this.addPoint.bind(this));

最后,这似乎是最好、最简洁的方法,尽管它看起来很愚蠢。如果没有bind功能,addPoint不知道它被调用的是哪个对象,并且没有第一个this,我什至找不到我的addPoint功能。

有没有更好的方法来完成这个看似简单的事情,或者最后一行代码是推荐的方法吗?


The forEach() https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/forEach方法和其他类似的数组方法,例如map() and filter()提供一个名为的可选参数thisArg专门用于此目的。

这作为this调用函数时提供给函数的“参数”:

ptList.forEach(this.addPoint, this);

当这样的参数不可用时,则选择使用闭包变量(变量名self经常用于此)或.bind()主要是一个偏好问题。请注意,另一种选择是在构造函数中定义函数并捕获闭包中的所有内容:

function Curve(ptList) {
  var pts = [];
  function addPoint(p) {
      pts.push(p);
  }

  if(ptList.length > 2) {
    ptList.forEach(addPoint);
  }

  this.addPoint = addPoint;
}

这比将函数放在原型上需要更多的内存,因为每个实例都有自己的副本(并且还排除了原型允许您执行的一些操作),但 Douglas Crockford(JSON 和 JSLint 的发明者)最近表示他甚至不使用this不再这样了,理由是内存很便宜,但 CPU 周期却不便宜(遍历原型链需要大量的处理)。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

在 forEach 中调用类函数:Javascript 如何处理“this”关键字 的相关文章