Array.of vs“[]”。何时使用Array.of而不是“[]”?

时间:2016-10-10 06:44:52

标签: javascript arrays

当我找到Array.of时,我正在做一些阅读。

根据MDN,

  

Array.of()方法创建一个具有可变数量参数的新Array实例,无论参数的数量或类型如何。

var a = Array.of(1,2,3,4,5);
console.log(a)

但如果我已经知道了这些值,我也可以将它们包装在[]中以获得相同的输出。那么当我们可以/应该使用Array.of时,是否存在特定情况?在[]上使用它还有什么好处吗?

编辑1:

此问题的目标是<{>> Array.of[]之间的差异,而不是new ArrayArray.of

之间的差异

3 个答案:

答案 0 :(得分:10)

Array.of()Array() / []构造函数之间存在一个细微差别。通常与Array()类似,this中的Array.of()将成为Array对象,它将使用Array.constructor function Array()构建它结果

但是Array.of可以通过更改绑定上下文来表现不同。如果绑定的上下文可以用作构造函数(如果绑定的对象是函数),它将使用该函数来构造。因此,让我们将Array.of()绑定到一个函数,看看会发生什么。

function Test(n){console.log(n)}
Test.prototype.last = function(){return this[this.length-1]};

var what = Array.of.call(Test, [5,6,7], {a:0,b:1}, 42, null, "this is last");
console.log(JSON.stringify(what,null,2));
console.log(what.last());

所以我们得到了一个类似于thingy的数组,可以访问所有函数方法以及构造函数原型中的

最好记住definition;

  

注2:功能是一种有意的通用工厂方法;它   不要求其值为Array构造函数。   因此,它可以转移到其他构造函数或由其他构造函数继承   可以使用单个数字参数调用。

好的,这对于数组子分类非常方便。我知道通过涉及Object.setPrototypeOf()__proto__可以进行数组子类化,但它们有点discouraged operations,我们仍然可以在Array.of()的帮助下完成类似的工作。所以...曾经被认为是无用的Array.of()在这里成为英雄;可能是最有用的数组方法之一。怎么会..?让我们看看......

function SubArr(){}
SubArr.prototype = Object.create(Array.prototype); // make SubArr.prototype's prototype Array.prototype
SubArr.prototype.last = function(){return this[this.length-1]}; // add prototype methods to SubArr

var what = Array.of.call(SubArr, 1, 2, 3, 4, "this is last");
console.log(JSON.stringify(what,null,2));
console.log(what.last());
console.log(what.map(e => e));
console.log(what instanceof Array);
console.log(Array.isArray(what));
console.log(Object.prototype.toString.call(what));

我也试过制作SubArr.prototype.constructor = Array;,但Array.isArray(what)仍然会产生false

答案 1 :(得分:2)

虽然这种方法可能已经标准化,但它似乎在许多浏览器中都不受支持,因此使用它似乎有风险,而且正如您所指出的那样,几乎毫无意义。

此函数的实用程序似乎适用于需要声明数组但不希望将其组装出部件的情况。也就是说,您希望能够将一些参数传递给某个函数,然后返回一个数组。

如果您按照指向该方法的理由的链接获得此信息:

用例是当你不能写一个文字时,因为你传递的函数 - 构造为funarg,并且最终的调用者可能只传递一个数字arg或几个args。在这种情况下,Array不会在one-number-arg的情况下做正确的事情。

这基本上是一种说法“这个函数可以接收可变长度的参数列表,并且将一致地返回填充了正确值的数组”,但实际上将数组转换为...数组,我并不完全确信这个东西需要存在,显然许多浏览器实现者都有类似的心态。

推动Array.of主要是对new Array()表现不一致这一事实的回应:

new Array(2);
// [ , ] 2-element array that's unpopulated

new Array(1,2);
// [1,2] 2-element array populated with the provided values

Array.of 始终的操作方式与后一版本相同。

答案 2 :(得分:0)

迭代Redu的答案,您可以使用ArraySubclass.of创建数组子类的实例。例如,您可以围绕lodash的Array方法创建一个Array-subclass包装器。

例如:

_.Array = class extends Array {
  uniq() {
    return _.Array.from(_.uniq(this));
  }
  last() {
    return _.last(this);
  }
  flatten() {
    return _.Array.from(_.flatten(this));
  }
  // ... more methods
}

_.Array.of([1,2,3], [3,4,5]) // <_.Array> [[1,2,3],[3,4,5]]
  .flatten()                 // <_.Array> [1,2,3,3,4,5]
  .uniq()                    // <_.Array> [1,2,3,4,5]
  .last()                    // <number> 5

<强> JSFiddle

修改

我最终扩展了这个例子以使用ES Proxies。

_.Array = class extends Array { }
_.Array.prototype = new Proxy(Array.prototype, {
  get(proto, name) {
    if (name in _) return function (...args) {
        const ret = _[name](this, ...args);
        return Array.isArray(ret) ? _.Array.from(ret) : ret;
    }
    return proto[name];
  }
});

现在每个lodash函数都可用,并且那些返回的数组包含在_.Array类中,类似于_(array)隐式链接。