自ECMA-262, 3rd Edition引入以来,Array.prototype.push
方法的返回值为Number
:
15.4.4.7 Array.prototype.push([item1 [,item2 [,...]]])
参数将按照它们出现的顺序附加到数组的末尾。 作为调用的结果,返回数组的新长度。
返回数组的新长度背后的设计决策是什么,而不是返回可能更有用的东西,例如:
为什么这样做,是否有关于如何做出这些决定的历史记录?
答案 0 :(得分:3)
我posted this in TC39's communication hub,并且能够进一步了解其背后的历史:
push
,pop
,shift
,unshift
最初是在1997年添加到JS1.2(Netscape 4)中的。以Perl中类似命名的函数为模型。
JS1.2 push遵循Perl 4约定,返回最后一个被推送的项目。 在JS1.3(1998年夏季的Netscape 4.06)中,更改了推送以遵循Perl 5约定,即返回数组的新长度。
请参阅https://dxr.mozilla.org/classic/source/js/src/jsarray.c#804
/* * If JS1.2, follow Perl4 by returning the last thing pushed. Otherwise, * return the new array length. */
答案 1 :(得分:2)
我无法解释为什么他们选择返回新的长度,但是回应你的建议:
鉴于JavaScript使用C样式赋值来发出指定值(而不是基本样式赋值),你仍然可以有这种行为:
var addedItem;
myArray.push( addedItem = someExpression() );
(虽然我知道这确实意味着你不能将它作为声明+赋值组合中r值的一部分)
这将是“流畅的”API的风格,在ECMAScript 3完成后显着获得了普及,并且它不会保持ECMAScript中其他库功能的风格,并且再次,它不是那么多额外的工作通过创建自己的push
方法来启用您所关注的方案:
Array.prototype.push2 = function(x) {
this.push(x);
return this;
};
myArray.push2( foo ).push2( bar ).push2( baz );
或:
Array.prototype.push3 = function(x) {
this.push(x);
return x;
};
var foo = myArray.push3( computeFoo() );
答案 2 :(得分:2)
因为你问我很好奇。我制作了一个示例数组并在Chrome中进行了检查。
var arr = [];
arr.push(1);
arr.push(2);
arr.push(3);
console.log(arr);
因为我已经引用了数组以及我推入的每个对象,所以只有一个其他属性可能有用......长度。通过返回Array数据结构的这一附加值,我现在可以访问所有相关信息。这似乎是最好的设计选择。如果您想为保存1台单机指令而争辩,那么或者根本不返回任何内容。
为什么这样做,是否有关于如何做出这些决定的历史记录?
毫无头绪 - 我不确定存在这些方面的理由记录。这将取决于实施者,并且很可能在任何给定的代码库中对实施ECMA脚本标准进行评论。
答案 3 :(得分:2)
我理解array.push()
期望返回变异数组而不是新长度。并希望将这种语法用于链接原因
但是,有一种内置方法可以执行此操作:array.concat[]
newArray = oldArray.concat[newItem];
可以使用.concat[]
代替.push()
来完成数组链接。
以下是React
中用于更改state
变量的常用模式,基于其先前值:
// the property value we are changing
selectedBook.shelf = newShelf;
this.setState((prevState) => (
{books: prevState.books
.filter((book) => (book.id !== selectedBook.id))
.concat(selectedBook)
}
));
state
对象具有books
属性,其中包含book
数组。
book
是一个包含id
和shelf
属性(以及其他)的对象
setState()
接受一个对象,该对象包含要分配给state
selectedBook
已在books
数组中,但其属性shelf
需要更改。
但是,我们只能给setState
一个顶级对象
我们不能告诉它去寻找这本书,并在那本书上找一个属性,并给它这个新的价值。
所以我们按原样采用books
数组
filter
删除selectedBook
的旧副本
然后concat
在更新selectedBook
属性后重新添加shelf
。
想要链接push
的好用例
但是,正确的方法是使用concat
。
要点:
array.push()
将返回一个数字(变异数组的新长度)
array.concat[]
将返回变异数组。