Array.of()无法按照es6中的指定工作?

时间:2017-08-12 17:37:31

标签: javascript arrays ecmascript-6

根据文档hereArray.of()new Array()的替代方法,可让您在运行时创建数组文字,即使它只有一个元素(a新的Array()发生故障的情况。我喜欢这样,并用new()替换了我的自定义数组子类上的大多数.of()调用,但是由于转换我现在在尝试某些事情时发现错误。

该链接声称.of()等同于此:

Array.of = function() { return Array.prototype.slice.call(arguments); }

为了检查这是否属实,我写了这个测试来比较真正的of()和那个polyfill:

Array.of_polyfill = function( ...args )           // Fake of().
{ 
    console.log( args );
    return Array.prototype.slice.call( args );
}

class A extends Array      // So we can peek inside what the real of() is doing.
{ 
    constructor( ...args )   // Using of() on an "A" calls this constructor. 
    { 
        console.log( args );
        return Array.prototype.slice.call( args );
    }
}

var a1 = A.of         ( 5,6,7,8 );
var a2 = A.of_polyfill( 5,6,7,8 );

a1和a2最终都包含正确的值[5,6,7,8],但在内部使用这两行是不一致的,如控制台日志中所示:

[4]
(4) [5, 6, 7, 8]

从第一行开始,调用.of()并不会导致整个文字在范围内,而只是[4],就像在内部调用A构造函数一样预分配四个槽,这不是polyfill所提到的。

我关心内部行为,因为of()的一个主要建议用法是自定义数组子类,如上面的A,以允许我指定新类型的数组文字。为此,我的A构造函数应该能够使用文字(传入的参数)进行手动操作,但由于上述原因,它无法访问它。是否有其他方式可以访问?

建议of()的polyfill是准确的还是我误解了JavaScript和构造函数的某些方面?

4 个答案:

答案 0 :(得分:2)

次要点... Array.of允许您创建一个数组,而不是“数组文字”。 “文字”是指允许您使用其初始化数据(如var a = [1, 2, 3])来描述和创建数组的语法。

最终,文档没有声明完全等效的polyfill。 MDN是一个wiki,所以如果可以改进polyfill,那么欢迎任何人提供更改。请记住,虽然它可以在ES5及更低版本中运行,但接近完整的子类化行为将会更加有效。

答案 1 :(得分:0)

所以我们在问题中混合了多个东西。您正在使用不应该使用的扩展运算符,并且似乎存在对本机代码的误解。 Array.of是一个静态函数;创建构造函数不会模仿其行为。但是,您可以覆盖静态方法并使用spread运算符。在这种情况下,它将是

class B extends Array {
    static of(...args) {
        return args;
    }
}

或使用参数

class A extends Array {
    static of() {
        return Array.prototype.slice.call(arguments);
    }
}

或者只是

class A extends Array {
    static of() {
        return Array.from(arguments);
    }
}

同样,你的“polyfill”做得太多了。通过使用扩展运算符,您将获得一个数组。这就足够了:

Array.of_polyfill = function (...args) {
    return args;
};

下面你会得到相同数组的三倍:

Array.of_polyfill = function (...args) {
    return args;
};

class A extends Array {
    static of() {
        return Array.prototype.slice.call(arguments);
    }
}

class B extends Array {
    static of(...args) {
        return args;
    }
}

var a1 = A.of(5, 6, 7, 8);
var a2 = A.of_polyfill(5, 6, 7, 8);
var b = B.of(5,6,7,8);

console.log(a1);
console.log(a2);
console.log(b);

这是ecmascript6中的函数声明:

/**
@param {...null} items
@static
@return {Array}
*/
Array.of = function(items) {};

答案 2 :(得分:0)

您假设使用传递给select count(*), group_concat(id) as listIds from posts p cross join (select min(p.id) as minid from posts p where p.id > 3 and p.deleted = true ) pp where p.id > 3 and (p.id < pp.minid or pp.minid is null); 的参数调用构造函数。那是错的。

让我们来看看Array.of的规范:

  
      
  1. len 成为传递给此函数的实际参数数。
  2.   
  3. 成为传递给此函数的参数列表。
  4.   
  5. C 为此值。
  6.   
  7. 如果A.of为真,那么

         

    一个。让 A IsConstructor(C)

  8.   
  9. 否则,

         

    一个。让 A ? Construct(C, « len »)

  10.         

    [...]

在我们的例子中,“C”是? ArrayCreate(len),你定义的类,它是一个构造函数。创建了一个新的A实例,使用“len”调用构造函数,这是我们传递给A的参数数量。

通常,构造函数为Array.of,因此将调用Array。在这里,调用Array(len)。因此,A(4)...args

之后,算法将使用正确的值填充新构造的数组。

这意味着[4]Array.of结果是等效的,但不是内部工作的方式。

答案 3 :(得分:0)

经过一些测试后,似乎Array.of()的实际实现是这样的:

Array.of = function() {
  //check wether `this` is a constructor, otherwise fall back to the `Array` constructor
  //maybe there's a better way to determine wether `this` is a constructor _before_ calling it.
  var constructor = typeof this === "function" && "prototype" in this? this: Array, 
    result = new constructor(arguments.length);

  for(var i=0; i<arguments.length; ++i)
    //FF and Chrome use defineProperty()
    Object.defineProperty(result, i, {
      value: arguments[i], 
      writable: true, 
      enumerable: true,
      configurable: true
    })
    //Edge simply assigns the values
    //result[i] = arguments[i];
    //didn't test IE, Opera, Safari or any mobile browser

  //and again, setting the length after the items have been defined
  result.length = arguments.length;
  return result;
}
  

为什么只是“某事” - 你没看过规范吗?

不,这是由浏览器中的实际行为驱动/推断的。而且只有“类似的东西”,因为我可能错过了一些东西。

特别是确定wet this的部分是一个实际的构造函数,我并不完全满意。如果您使用箭头功能并手动添加名为prototype的属性,它可能会产生错误匹配(然后抛出);但那种黑客行为应该非常罕见。

  

“经过一些测试” - 你测试了什么?

  • 该功能在不同环境中的表现,
    附加到函数,consturctor函数,非构造函数,一般对象,
  • 将它附加到某个对象或用Function#call调用它之间有区别,
  • wether以及传递给函数constuctor的参数。
  • constructorconstructor.prototype.constructor不相同时的行为方式
  • 在原型链中需要Array(以回退到Array-constructor),
  • 基本上它如何确定初始化返回对象的构造函数
  • 如果我预定义索引和length - proeprty(如果属性不是configurable:true则抛出错误,但仅在FF和Chrome中)会发生什么情况