Ever since its introduction in ECMA-262, 3rd Edition, the Array.prototype.push
method's return value is a Number
:
15.4.4.7 Array.prototype.push ( [ item1 [ , item2 [ , … ] ] ] )
The arguments are appended to the end of the array, in the order in which they appear. The new length of the array is returned as the result of the call.
What were the design decisions behind returning the array's new length, as opposed to returning something potentially more useful, like:
- A reference to the newly appended item/s
- The mutated array itself
Why was it done like this, and is there a historical record of how these decisions came to be made?
I understand the expectation for
array.push()
to return the mutated array instead of its new length. And the desire to use this syntax for chaining reasons.However, there is a built in way to do this:
array.concat[]
newArray = oldArray.concat[newItem];
Array chaining can be accomplished by using
.concat[]
instead of.push()
.Here is a common pattern used in
React
for changing thestate
variable, based on its prior value:state
object has abooks
property, that holds an array ofbook
.book
is an object withid
, andshelf
properties (among others).setState()
takes in an object that holds the new value to be assigned tostate
selectedBook
is already in thebooks
array, but its propertyshelf
needs to be changed.We can only give
setState
a top level object, however.We cannot tell it to go find the book, and look for a property on that book, and give it this new value.
So we take the
books
array as it were.filter
to remove the old copy ofselectedBook
.Then
concat
to addselectedBook
back in, after updating it'sshelf
property.Great use case for wanting to chain
push
.However, the correct way to do this is actually with
concat
.Summary:
array.push()
will return a number (mutated array's new length).array.concat[]
will return the mutated array.I was curious since you asked. I made a sample array and inspected it in Chrome.
Since I already have reference to the array as well as every object I push into it, there's only one other property that could be useful... length. By returning this one additional value of the Array data structure, I now have access to all the relevant information. It seems like the best design choice. That, or return nothing at all if you want to argue for the sake of saving 1 single machine instruction.
No clue - I'm not certain a record of rationale along these lines exists. It would be up to the implementer and is likely commented in any given code base implementing the ECMA script standards.
I cannot explain why they chose to return the new length, but in response to your suggestions:
Given that JavaScript uses C-style assignment which emits the assigned value (as opposed to Basic-style assignment which does not) you can still have that behavior:
(though I recognise this does mean you can't have it as part of an r-value in a declaration+assignment combination)
That would be in the style of "fluent" APIs which gained popularity significantly after ECMAScript 3 was completed and it would not be keeping in the style of other library features in ECMAScript, and again, it isn't that much extra legwork to enable the scenarios you're after by creating your own
push
method:or: