-1

I understand that JavaScript apply() considers the 2nd param as as array param arg for the fn which its being applied to. However in this current code snippet below, item arg is [1,2] instead of [[1,2], 6,7,8,9]

Can someone explain to me as to why this happens?

var orig = [1, 2],
    add = [6,7,8,9];

prependArgs.apply(orig, $.merge([orig], add.slice(0)));

function prependArgs(item) {
    // item = [1,2] instead of [[1,2], 6,7,8,9] -- Why? 
    var a = item.slice(0);
    for (var i = 0; i < a.length; i++) {
        this.unshift(item[i]);
    }
}
  • 1
    You probably want `call` not `apply`. – elclanrs Jul 12 '14 at 23:02
  • 1
    I understand the difference between call and apply. My question is why is item not equal to the whole array, but instead just [1,2]. Any ideas? – user3832933 Jul 12 '14 at 23:04
  • if your `prependArgs` is defined as `prependArgs(item, x)`, then `x` would be `6`, if you want the whole array passed in, may be you need to wrap `[$.merge([orig], add.slice(0))]` (array of array). – King King Jul 12 '14 at 23:08
  • 4
    @user3832933: because you are using `apply`, not `call`. If you used `call` it would be equal to what you "expect". It's like a Heisenberg understanding: you understand the difference and you don't in the very same time :-D – zerkms Jul 12 '14 at 23:08
  • 1
    possible duplicate of [What is the difference between call and apply?](http://stackoverflow.com/questions/1986896/what-is-the-difference-between-call-and-apply) – King King Jul 12 '14 at 23:23
  • even if this code worked like you wanted it to, you would end up with `orig` self referencing itself in the element at index 4 – Patrick Evans Jul 12 '14 at 23:38
  • It seems like you don't understand `.apply()` after all. Every element of the array becomes an argument passed to the function. The first element is `[1,2]`, hence `item` gets the value `[1,2]`. – Felix Kling Jul 13 '14 at 00:14

2 Answers2

1

The result of your $.merge is [Array[2], 6, 7, 8, 9]

function.apply() takes an array of items, and divide it into a number of separate arguments - one for each element of the array. The first argument item is therefore [1,2] because that is the first element of the array you passed.

apply() did take the rest of elements and passed them as additional arguments which you would see by declaring your function as prependArgs(item, item2, item3, item4, etc..), or by doing this:

function prependArgs(item) { console.log(arguments) // prints [Array[2], 6, 7, 8, 9] }

function.call() would pass the entire array as the single argument item without splitting it.

mtone
  • 1,400
  • 13
  • 29
0

To get the whole array inside the function call using apply(), try this

var orig = [1, 2],
    add = [6,7,8,9];

prependArgs.apply(orig, [$.merge([orig], add)]);  

function prependArgs(item) {

    console.log(item)  //--- this prints [[1, 2], 6, 7, 8, 9] 
    var a = item.slice(0);
    for (var i = 0; i < a.length; i++) {
        this.unshift(item[i]);
    }
}

as pointed out in the comments, if you want to use apply() you need to pass an array as the second argument, see documentation here

BeNdErR
  • 15,879
  • 16
  • 63
  • 97
  • Why to wrap it in an additional array if there is a dedicated `call()` function invented for this exact case? – zerkms Jul 12 '14 at 23:13
  • 1
    you are right, but if he wants to use `apply()` that's how he should do it. – BeNdErR Jul 12 '14 at 23:15
  • "but if he wants" --- it makes sense to tell them the "right" way of doing that. Newbies want weird things just because of lack of experience. And we are here to shed some light for them on how to do it instead. – zerkms Jul 12 '14 at 23:16
  • the OP asked why his code was not working, telling us that he understood the difference between apply and call. May I ask you why `call` is the "right" way of doing that instead of using `apply`? It's just the *array wrap* thing or there's something more? – BeNdErR Jul 12 '14 at 23:23
  • 2
    "he understood the difference between apply and call" --- as you can see it's not the case. " why call is the "right" way of doing that instead of using apply"- you surely can. Because it makes no sense to create another array just instead of using an explicitly designed function. "It's just the array wrap" --- it's not "just", it's code clarity and maintanability. Everything in your code must be added for reason. If your code doesn't express your exact intentions - it will be hard to understand for further reader. It would take me extra time to realize why one used apply instead of call here. – zerkms Jul 12 '14 at 23:25
  • actually your solution is wrong matter if you use call or apply. _"[1,2] instead of [[1,2], 6,7,8,9]"_ by his comment he wants `item` to be an array with the first element being the array `[1,2]`, and the rest of the array elements being the values 6-9. Not an array whose elements are the values 1-9 – Patrick Evans Jul 12 '14 at 23:28
  • @zerkms thanks for the time spent to explaining your point. Please answer the OP question with your solution – BeNdErR Jul 12 '14 at 23:31