cssGEEK
cssGEEK

Reputation: 1014

Rewrite following piece of javascript code

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

Answers (4)

Redu
Redu

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

axelduch
axelduch

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

alexmac
alexmac

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

ssube
ssube

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

Related Questions