使用' thisArg'的Nodejs方法并且'使用严格的&#39 ;;问题

时间:2014-05-06 01:49:37

标签: javascript node.js strict

我在Fedora 19上安装了v8 v.1.14.5节点和V8 v3.14.5.9。我遇到的问题是使用thisArg可选参数的方法,如Array.prototype.forEach

如果我在Chromium v​​33或Firefox v28上执行以下代码 - jsFiddle

var y = [1, 2, 3];

y.forEach(function (element) {
    console.log(this);
}, 'hej');

我得到

的输出
String {0: "h", 1: "e", 2: "j", length: 3}
String {0: "h", 1: "e", 2: "j", length: 3}
String {0: "h", 1: "e", 2: "j", length: 3}

然后是相同的代码,但是在严格模式下 - jsFiddle

var y = [1, 2, 3];

y.forEach(function (element) {
    'use strict';
    console.log(this);
}, 'hej');

我得到了一个输出

hej
hej
hej

根据ECMA5规范sec-function.prototype.call,这些是我期望的结果。

  

thisArg值未经修改即作为此值传递。这是对版本3的更改,其中未定义或null thisArg替换为全局对象,ToObject应用于所有其他值,并将结果作为此值传递。即使thisArg未经修改就通过,非严格模式函数在进入函数时仍会执行这些转换。

,例如sec-array.prototype.foreach

  

如果提供了thisArg参数,则每次调用callbackfn时都会将其用作此值。如果未提供,则使用undefined。

和相关的伪代码

Let funcResult be the result of calling the [[Call]] internal method of callbackfn with T as thisArgument and a List containing kValue, k, and O as argumentsList.

然而,在节点上,上述两个片段都返回

{ '0': 'h', '1': 'e', '2': 'j' }
{ '0': 'h', '1': 'e', '2': 'j' }
{ '0': 'h', '1': 'e', '2': 'j' }

任何人都可以确认这是否是我的节点环境的问题,或者这是否与节点有关?

更新:只是为了确认,在节点typeof this的两种情况下都会返回object

1 个答案:

答案 0 :(得分:3)

与V8 v3.14.5.9(及更早版本)一起安装的节点v0.10.28(最新稳定版)存在问题,但问题不是节点本身,而是V8,它有一个错误。

错误报告可在2012年8月5日发布的issue 2273中找到。

  

严格模式功能应该接收非强制'this'值。也就是说,'this'可以是undefined / null而不是全局对象,而是原始值而不是盒装值。

     

调用者函数是否处于严格模式并不重要。但是,即使要调用的函数处于严格模式,“Array.prototype.forEach”等内置函数也会错误地执行强制操作。

     

测试用例:

(function() {
  var logger = function() {
    "use strict";
    console.log(this);
  };

  var strictCaller = function() {
    "use strict";
    logger.call("foo");
  };

  var nonStrictCaller = function() {
    logger.call("foo");
  };

  var forEachCaller = function() {
    [123].forEach(logger, "foo");
  };


  // call from strict function: logs primitive value
  strictCaller();

  // call from non-strict function: logs primitive value
  nonStrictCaller();

  // call through forEach: logs *boxed* value (WRONG)
  forEachCaller();
})();

错误修复已于2013年4月5日在revision r14149中提交给V8源代码

因此问题长期存在,影响了所有基于V8引擎的环境。

我能够确认Chrome v27仍然受此问题影响且运行V8 v 3.16,并且可以确认Chrome v34与V8 v3.24.35.33不再受影响。因此,在这两者之间,V8的修复成为主流。

@cookiemonster的建议一个解决方案可能是使用更高版本的节点(来自他们不稳定的仓库),但我无法证实这一点。

我无法在node issues list中找到有关此问题的任何报告。

唯一的其他解决方案是测试此错误(上面给出的代码)并自己填充受影响的方法。我已经测试了这个解决方案并且它可以工作,这是我测试过的垫片。 (取自es5-shim project

Array.prototype.forEach = function forEach(fun /*, thisp*/ ) {
    'use strict';
    var object = Object(this),
        thisp = arguments[1],
        i = -1,
        length = object.length >>> 0;

    // If no callback function or if callback is not a callable function
    if (Object.prototype.toString.call(fun) !== '[object Function]') {
        throw new TypeError(); // TODO message
    }

    while (++i < length) {
        if (i in object) {
            // Invoke the callback function with call, passing arguments:
            // context, property value, property key, thisArg object
            // context
            fun.call(thisp, object[i], i, object);
        }
    }
};

该问题已被采纳:

  1. idiomatic.js
  2. es5-shim
  3. nodejs