英文:
Why does Array.of exist?
问题
为什么存在Array.of
?据我所知,它只是从传递的参数创建一个数组(例如Array.of(1,2,3)
-> [1,2,3]
)。
这个JSPerf显示,这个简单的替代函数(它的工作方式完全相同)比Array.of
快80-90%。
const array_of = (...args) => [...args];
^ 这是有效的ES6语法,Array.of
也是如此。
英文:
Why does Array.of
exist? AFAIK it simply creates an array from the arguments passed (i.e Array.of(1,2,3)
-> [1,2,3]
).
This JSPerf shows that this simple replacement function (which works exactly the same way) performs 80-90% faster than Array.of
const array_of = (...args) => [...args];
^ this is valid ES6 and so is Array.of
答案1
得分: 2
这完全没问题。向函数传递大量参数并创建其堆栈帧只是一项昂贵的操作。
此外,如果您参考文档,它是Array
的静态方法:
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/of
因此,还有其他情景可以使用它,例如子类化Array
,这样您可以创建您的Array
子类的实例。这可能很有用,例如将其作为对您的子类的工厂的引用传递。
虽然在通常用于Web应用程序中的数据大小上性能较差,但这可能并不重要。
英文:
That's totally OK. Passing a lot of parameters to a function and creating its stack frame is just an expensive operation.
Also if you refer to the documentation, it's a static method of Array
:
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/of
So there're additional scenarios how to use it, like subclassing Array
so you can create instances of your subclass of Array
. That could be useful, like passing it by reference as a factory for your subclass.
While its less performant that could be not important on usual data sizes used in web app.
答案2
得分: 2
我还可以说,这是因为Array.of
可以在不支持扩展运算符的旧浏览器中使用。它是**ECMAScript 6(ES6)**的一部分,是内置对象。它与其他内置方法(例如Array.from
和Array.map
)更一致。
其主要原因是提供比传统的Array构造函数更可预测的构造函数。
这意味着当你创建Array(3)
时,它创建一个长度为3的空数组,而不是一个只包含一个元素3的数组。而在Array.of
的情况下,它始终根据传递给它的参数创建数组,这有助于避免产生意外的结果。
英文:
I can also say that it is because of Array.of
can be used in older browsers that do not support the spread operator. It is the part of ECMAScript 6 (ES6) as built-in object. It is more consistent with other built-in methods, such as Array.from
and Array.map
.
> The main reason for, it is to provide more predictable constructor than the traditional Array constructor.
This above means that when you create Array(3)
it creates an empty array length 3, not an array with single element, 3. In case of Array.of
It always creates an array with the arguments you pass to it. which is good to not making unexpected results.
答案3
得分: 1
公平的问题。我将尝试给出公平的回答。
我的观点是
const arr = Array.of(...args);
比
const arr = (...args) => [...args];
更清晰。
为什么?
在这两种情况下,我们都在创建一个新数组。这很关键,因为数组是按引用处理的。长话短说:我们都同意下面的代码将更新两个数组:
const x = [1, 2, 3];
const y = x;
y.push(4);
console.log(x, y);
x 和 y 数组现在都有4个元素,因为y只是对已创建的x数组的引用。对y的任何修改都将影响由x和y引用的实例。
这就是为什么当我们克隆复杂类型(而不是原始类型)时,我们希望新实例是分离的,不会影响原始值。在我们的示例中,我们将进行以下修改以获得更期望的结果:
const x = [1, 2, 3];
const y = Array.of(...x);
y.push(4);
console.log(x, y);
很明显y是x的克隆,对我来说至少比以下方式更清晰:
const x = [1, 2, 3];
const y = (...args) => [...args]; // 同样的效果,但我们确定我们理解发生了什么吗?
y.push(4);
console.log(x, y);
我的问题是: 为什么要止步于此?如果我们需要克隆一个对象呢?
虽然有些人认为这是一个很酷的方法:
const x = { hello: 'world' };
const y = { ...x };
但我认为经典的方式更可读:
const x = { hello: 'world' };
const y = Object.assign({}, x);
你不必成为JavaScript大师才能理解它。
另外,值得一提的是,对于这两种情况,你都可以使用以下方式来克隆:
const x = { something: 'else', with: [{ 'way': 'more' }, levels: [1, 2, 3]] };
const y = JSON.parse(JSON.stringify(x));
这是一种非常简单的方法(或者说是一种不太正规的方法),用于序列化和反序列化一个对象,创建其完美的克隆。
总之:
当性能很重要时,团队的表现也至关重要。他们很可能会理解并且更欣赏性能更好的代码(并且可能会对遇到 forEach
循环时感到不满)。
在其他情况下,保持代码简单,以便其他人可以维护你的代码库。
干杯!
英文:
Fair question. I will try to give it a fair answer
My argument is that
const arr = Array.of(...args);
Is more clear than
const arr = (...args) => [...args];
Why?
In both cases we are creating a new array. This is crucial because arrays are handled by reference. Long story short: we all agree that the below code will update both arrays
const x = [ 1, 2, 3 ];
const y = x;
y.push(4);
console.log(x, y);
Both x and y arrays has now 4 elements, because y is only a reference to the already created x array. Any modification in y will address the instance referenced by both x and y
That is why, when we are cloning complex types (not primitives) we intend the new instance to be separated and not affect the original value. In our example, will will make the following modification to get more excepted results
const x = [ 1, 2, 3 ];
const y = Array.of(...x);
y.push(4);
console.log(x, y);
It is clear that y is a clone of x, for me at least, way more than just
const x = [ 1, 2, 3 ];
const y = (...args) => [...args]; // smae effect, still - are we sure we understand what's going on?
y.push(4);
console.log(x, y);
My question is: why stopping here? What if we need to clone an object instead?
While some argue that this is a cool way to do it
const x = { hello: 'world' };
const y = { ...food };
I think that the classic way is more readable
const x = { hello: 'world' };
const y = Object.assign({}, x);
You don't have to be javascript master in order to understand it
Also, it worth mentioning that for both cases you can make a clone by using
const x = { something: 'else', with: [ { 'way': 'more' }, levels: [ 1, 2, 3 ] ] };
const y = JSON.parse(JSON.stringify(x));
Which is a very simple way (or a dirty hack) to serialize and desterilize an object, creating a perfect clone of it
In conclusion:
When performance matters, the performance of the team is crucial as well. Most chances that they will understand and also appreciate more performant code (and will probably be bitter whenever they encounter forEach
loop)
In any other case, keep it simple for other humans to maintain your code base
Cheers
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论