【问题标题】:The invocation context (this) of the forEach function callforEach 函数调用的调用上下文(this)
【发布时间】:2013-10-31 13:34:36
【问题描述】:

我想知道 forEach 回调函数的“this”值(或调用上下文)是什么。此代码似乎不起作用:

var jow = [5, 10, 45, 67];

jow.forEach(function(v, i, a){

    this[i] = v + 1;

});

alert(jow);

感谢您向我解释。

【问题讨论】:

标签: javascript function foreach this invocation


【解决方案1】:

MDN 声明:

array.forEach(callback[, thisArg])

如果为 forEach 提供了 thisArg 参数,它将被用作 每次回调调用的 this 值就像 callback.call(thisArg, 元素,索引,数组)被调用。如果 thisArg 未定义或为空, 函数内的this值取决于函数是否 是否在严格模式下(如果在严格模式下,则传递值,全局对象 如果在非严格模式下)。

所以简而言之,如果您只提供回调并且您处于非严格模式(您提出的情况),它将是全局对象(窗口)。

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/forEach

【讨论】:

  • 这很奇怪。如果我在一个对象上创建一个方法,那么“this”值就是那个对象。为什么会有所不同?
  • this 在 forEach 的主体中确实是您的特定数组,但它与您提供的回调之间没有联系。回调被调用,但是 forEach 的实现需要,特别是 thisArg、窗口或元素作为 this。
  • 谢谢,我快到了...我使用 jow 数组作为 thisArg,但我得到了不好的结果:jsfiddle.net/39LSg。这是为什么? -this- 的值似乎随着 window 对象和 jow 数组之间的每次迭代而跳跃
  • 您正在使用数组中的值作为要更改的元素的索引。第一次迭代将 jow[1] 更改为 5(将 2 替换为 5),第二次将 jow[5] 更改为 5(在末尾添加另一个 5),第三次将 jow[3] 更改为 5(将 4 替换为 5),每隔一个迭代将 jow[5] 更改为 5。
  • MDN says, In strict mode, however, the value of this remains at whatever it was set to when entering the execution context。在类方法的上下文中,作为 forEach 的参数传递的嵌套经典函数将保留原始类实例作为 t​​his 值(假设函数不是强制的),听起来像箭头函数的行为不是吗!?
【解决方案2】:

我完成了 forEach 方法的构建,并想与大家分享这个图表,希望它能帮助其他人试图理解它的内部工作原理。

【讨论】:

  • lol 这个图中的间距实际上没有任何意义
  • 我的意思是总体布局,这个图完全看不懂
  • forEach() 上下文应该在 this 上下文中。在 sdev 中,上下文几乎总是包裹它的孩子。我确实喜欢 UML 风格的方法。
【解决方案3】:

如果不将第二个参数传递给forEachthis 将指向全局对象。为了实现你想要做的事情

var jow = [5, 10, 45, 67];

jow.forEach(function(v, i, a) {
    a[i] = v + 1;
});

console.log(jow);

输出

[ 6, 11, 46, 68 ]

【讨论】:

    【解决方案4】:

    在 forEach 内部,this 指的是全局 window 对象。即使您从不同的对象(即您创建的对象)调用它也是如此

    window.foo = 'window';
    
    var MyObj = function(){
      this.foo = 'object';
    };
    
    MyObj.prototype.itirate = function () {
      var _this = this;
    
      [''].forEach(function(val, index, arr){
        console.log('this: ' + this.foo); // logs 'window'
        console.log('_this: ' + _this.foo); // logs 'object'
      });
    };
    
    var newObj = new MyObj();
    
    newObj.itirate();
    // this: window
    // _this: object
    

    【讨论】:

    • 这基本是真的。但是你可以在回调之后传递一个thisArg 来定义this 所指的内容。在您的示例中,您可以调用[''].forEach(function (…) {…}, myObj),这样this.foo 将返回'object' 而不是'window'
    • 有趣的是,默认情况下,thisArg 指的是全局window 对象(我已经在我的浏览器中测试过),而在规范中它说如果没有@提供了 987654334@,默认为undefined。 MDN:developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…。规格:ecma-international.org/ecma-262/5.1/#sec-15.4.4.18
    【解决方案5】:

    对于“this”上下文问题,我有一个非常简单的方法,它是这样的: 每当您想知道“this”的上下文是什么时,如果左侧没有调用者,则检查谁留给调用者,否则它是该对象实例:

    示例:

    let obj = { name:"test", fun:printName }
    
    function printName(){
      console.log(this.name)
    }
    
    //who is left to the caller? obj! so obj will be 'this'
    obj.fun() //test
    
    //who is left to the caller? global! so global will be 'this'
    printName() //undefined (global has no name property)

    因此,对于“foreach”的情况,当您提供回调函数时,foreach 实现中实际发生的情况是这样的:

    --> 你调用 [1,2,3].foreach(callback,'optional This')

     foreach(arr,cb)
     {
      for(i=0; i<arr.len;i++)
      {
       //who is left to the caller? global! so it will be 'this'
       cb(arr[i])
      }
     }

    除非 - 你给它可选的 'this' 或者你用 this 绑定回调(例如箭头函数) 如果发生这种情况,那么被调用的回调已经有一个“this”obj,哪种“阻止”你改变它给定的上下文 更多关于绑定的信息可以在这里找到enter link description here 但基本上绑定实现如下所示:

    Function.prototype.bind = function (scope) {
        var fn = this;
        return function () {
            return fn.apply(scope);
        };
    }

    所以您可以看到 fn(您的回调)将始终使用您的 'this'(范围)调用

    希望对你有帮助...

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-02-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多