【问题标题】:Why does this function with "this" not work? About "this" and its scope为什么这个带有“this”的功能不起作用?关于“this”及其范围
【发布时间】:2019-02-19 01:24:25
【问题描述】:

我知道以这种方式向原型添加方法不是最好的,但我只是在测试。

Array.prototype.maap = function (transform) {
  let mapped = [];
  for (let element of this) {
        mapped.push(transform(element));
  }
  return mapped;
}

console.log([0, 2, 3].maap(n => n / this.length));

我得到:

[NaN,无穷大,无穷大]。我认为问题在于“this.length”。

【问题讨论】:

    标签: javascript scope this


    【解决方案1】:

    你是对的,问题是this.length。问题是它不在函数中!它在一个 lambda 中,其范围不是稍后调用它的数组的范围。因此,this 不是数组,this.length 是实心 0(0/0 是 NaN,2/0 是无穷大,3/0 也是无穷大)。

    您可以硬编码实际值3,或者将您的逻辑移到函数本身中。或者您可以让 lambda(实际上是 JavaScript 中的“箭头函数”)采用另一个参数:分母的参数。

    Array.prototype.maap = function (transform) {
      let mapped = [];
      for (let element of this) {
            mapped.push(transform(element, this.length));
      }
      return mapped;
    }
    
    console.log([0, 2, 3].maap((n, m) => n / m));

    【讨论】:

    • 谢谢。当我对“this”进行控制台登录时,我确实注意到它是“window”,但不明白为什么。我认为它会采用 maap 的 this,即数组,因为根据雄辩的 javascript 书,“箭头函数是不同的——它们不绑定自己的 this,但可以看到它们周围范围的 this 绑定”。我认为 maap 函数限定为“它周围的范围”。
    • @SRCP 但是箭头函数不在 maap 函数中。它被传递给 maap 函数。它只是在全局范围的代码中用作函数参数的表达式。
    • 啊,我明白了。它是一个功能让我感到困惑。最后,它只返回一个值,即参数。明白了。
    • @SRCP:有点,是的。最好认为它是 论点。它并没有真正返回值,也不是在那里调用的函数。它一个函数。这有点像你只是写了console.log([0,2,3].maap(nameOfAFunctionThatAlreadyExists)。事实上,这正是它的样子。
    【解决方案2】:

    箭头函数内的this 在其包含块中引用相同的this。这里,包含块是顶层,其中this 指的是windowwindow.length0

    console.log(this === window);
    console.log(window.length);

    所以,你的代码相当于:

    Array.prototype.maap = function(transform) {
      let mapped = [];
      for (let element of this) {
        mapped.push(transform(element));
      }
      return mapped;
    }
    
    console.log(this.length);
    console.log([0, 2, 3].maap(n => n / 0));

    0 / 0undefined,而大多数其他号码 / 0Infinity(或 -Infinity)。

    如果您想用this 模拟Array.prototype.map 的行为,传递给maap 的第二个参数应该是调用回调的this 值:

    Array.prototype.maap = function(transform, thisVal) {
      let mapped = [];
      for (let element of this) {
        mapped.push(transform.call(thisVal, element));
      }
      return mapped;
    }
    
    const arr = [0, 2, 3];
    console.log(arr.maap(
      function(n){ return n / this.length; },
      arr
    ));

    【讨论】:

      【解决方案3】:

      我认为问题出在箭头函数上(参数transform),是的,this.length是直接相关的问题,再深入一点,是关于arrow function的问题,

      箭头函数没有自己的this。使用封闭词法范围的this 值;

      简单地说,箭头函数定义了this指向的地方。

      所以,对于你的代码,你传入的参数是n => n / this.length,它是在window环境下的函数console.log中定义的。所以真正的问题是:

      transf = (n) => {
        console.log(this);    // Window {postMessage: ƒ, blur: ƒ, focus: ƒ, close: ƒ, parent: Window, …}
        return n / this.length
      }
      console.log([0, 2, 3].maap(transf));
      

      【讨论】:

        猜你喜欢
        • 2011-05-11
        • 1970-01-01
        • 2014-04-03
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-08-12
        • 1970-01-01
        相关资源
        最近更新 更多