Reputation: 1014
I am trying to create a function that mimics Array.prototype.push. It takes a variable number of arguments and pushes them into a specific array. I have managed to do this with the following code:
var array=[];
function append(){
for(var i=0;i<arguments.length;i++)
array.push(arguments[i]);
}
Now my question is:Can I rewrite the append function without using "for loop"? Thanks in advance.
Upvotes: 2
Views: 128
Reputation: 26191
Actually i honestly believe that push must be redefined for the functional JS since it's returning value is the length of the resulting array and it's most of the time useless. Such as when it's needed to push a value and pass an array as a parameter to a function you cant do it inline and things get messy. Instead i would like it to return a reference to the array it's called upon or even a new array from where i can get the length information anyway. My new push proposal would be as follows;
Array.prototype.push = function(...args) {
return args.reduce(function(p,c) {
p[p.length] = c;
return p
}, this)
};
It returns a perfect reference to the array it's called upon.
Upvotes: 0
Reputation: 10849
You could use Array.prototype.push.apply
function append(){
// make arguments an array
var args = Array.prototype.slice.call(arguments);
// return the number of elements pushed in the array
return Array.prototype.push.apply(array, args);
}
So, what's happening here with args
? We use Array.prototype.slice.call
with arguments, the purpose being to make arguments
an array, because it is a special object. Function.prototype.call
is used to call a function with a specific context (aka this
), and then the arguments to call the function with (comma separated). Conveniently, it appears that slice()
looks at the length
property of the this
context, and arguments
has one too, and when not empty, has properties from 0 to length -1
, which allows slice
to copy arguments
in a new array.
Upvotes: 1
Reputation: 19617
If you need to get arguments array, you should use Array's slice function on an arguments object, and it will convert it into a standard JavaScript array:
var array = Array.prototype.slice.call(arguments);
Upvotes: 2
Reputation: 48327
You can rewrite this without a for
loop, but you have to use a loop of some sort (you're working with multiple items, it's a necessity).
If you have access to ES6 or Babel, I would use something like:
function append(...args) {
return array.concat(args);
}
Without ES6, you need to work around the fact that arguments
isn't a real array. You can still apply most of the array methods to it, by accessing them through the Array
prototype. Converting arguments
into an array is easy enough, then you can concat
the two:
function append() {
var args = Array.prototype.map.call(arguments, function (it) {
return it;
});
return array.concat(args);
}
Bear in mind that neither of these will modify the global array
, but will return a new array with the combined values that can be used on its own or assigned back to array
. This is somewhat easier and more robust than trying to work with push
, if you're willing to array = append(...)
.
Upvotes: 0