Ivan Vashchenko
Ivan Vashchenko

Reputation: 1224

Javascript array mutation in looping with a callback

I implement looping with a callback using call() function (example from http://ejohn.org/apps/learn/#28, see below)

function loop(array, fn){ 
  for ( var i = 0; i < array.length; i++ ) 
    fn.call( array, array[i], i ); 
}

To modify contents of the array, I can use

var a = [0,1,2]
loop(a, function(v, i) { this[i] = 0; }); // a = [0,0,0]

but not

var a = [0,1,2]
loop(a, function(v, i) { v = 0; }); // a = [0,1,2]

Why does that happen? this is array, so this[i] and array[i] and v are the same. However, in one case the array is modified, in another it stays immutable.

Upvotes: 0

Views: 1002

Answers (2)

MT0
MT0

Reputation: 168081

When fn.call( array, array[i], i ); is invoked then within fn():

  • this stores a reference to array;
  • v is a variable storing the value of array[i] (and can be thought of as doing var v = array[i]; at the start of the function's scope); and
  • i is a variable storing the value of the current index of the array.

Note that this stores a reference whereas v and i are variables storing values.

In the first function (loop(a, function(v, i) { this[i] = 0; });) is the equivalent, for each array element, of var v = a[i]; a[i] = 0; (since this within the function is a) and so the array is updated as the value 0 is assigned to the given index of the array.

However, in the second function (loop(a, function(v, i) { v = 0; });) is the equivalent, for each array element, of var v = a[i]; v = 0; and so the array is not updated as the value '0' is assigned to a variable v within the function's scope and not to the array.

Upvotes: 2

megawac
megawac

Reputation: 11363

Because reassigning a variable in javascript will not update whatever that variable was referencing. In the first snippet you are reassigning the index i of an array to the new value 0. In the second snippet you are just reassigning the v to 0 which will not modify the array.

Essentially what you're doing to simply is

var a = [1,2,3];
//first case
var v = a[1];
a[1] = 0;
//Array value of index 1 is updated

//second case
var v = a[1];
v = 2;
//array value of index 1 is not updated

Upvotes: 0

Related Questions