替换下划线的 toArray

Replacement for underscore's toArray

我正在开发一个超级简单的流星应用程序,发现一些代码几乎完全符合我的要求,但依赖于 underscorejs。我从来没有使用过 underscorejs 并且不想有这种依赖(我当然听说过 underscore 很棒,但我现在不想处理任何不必要的包)。这是唯一使用 underscorejs 的行:

this.channels[name].args = _.toArray(arguments);

重写 toArray 函数是微不足道的,还是在幕后进行了一些繁重的工作?

代码来自此博客条目:http://www.manuel-schoebel.com/blog/meteorjs-package-only-app-structure-with-mediator-pattern 并且位于 Mediator 对象示例中。

谢谢!

如果那是原生 arguments 对象,您可以迭代并创建一个数组

var arr = [];

for (var i=0; i<arguments.length; i++) {
    arr[i] = arguments[i]
}

或者您可以使用原生 Array.prototype.slice.call,缩写为 [].slice.call

var arr = [].slice.call(arguments);

请注意,MDN 明确表示

You should not slice on arguments because it prevents optimizations in JavaScript engines (V8 for example). Instead, try constructing a new array by iterating through the arguments object.

如果您对下划线评分并相信它在做什么,您可以使用此处的 toArray 方法:http://underscorejs.org/docs/underscore.html#section-46

_.toArray = function(obj) {
  if (!obj) return [];
  if (_.isArray(obj)) return slice.call(obj);
  if (isArrayLike(obj)) return _.map(obj, _.identity);
  return _.values(obj);
};

不幸的是,下划线使用下划线!所以你必须实施 isArray,并且 isArrayLike 也 :P

也许来源可以为您提供一些关于您希望您的实现如何工作的想法?

此外,请查看 lodash 源代码。这也可能会提供一些灵感:https://github.com/lodash/lodash/blob/master/lodash.js#L8983

arguments 是一个可迭代对象,虽然它不是明确的 Array。如果你不关心 JS 引擎的影响,你可以简单地将它转换为一个真正的数组。这允许您将 arguments 视为数组并执行数组方法。你可以这样做:

this.channels[name].args = Array.prototype.slice.call(arguments);

另一种方式是:

this.channels[name].args = Array.apply(null, arguments);

如果你想替换_.toArray()而不依赖下划线库,你可以这样做:

_.toArray = function () { return Array.prototype.slice.call(arguments)[0]; };

ES6 将有 spread operator 可以优雅地做你想做的事情:

function someFunction(...args) { 
    this.channels[name].args = args;
}