Javascript Eval overwriting variable

2019-03-04 01:49发布

问题:

Don't understand why the code below is overwriting my var arr. Any help appreciated.

var arr = [1,2,3]

var string = "function swap(arr) { var newarr = arr; var temp = arr[0]; newarr[0] = arr[arr.length-1]; newarr[arr.length-1] = temp; return newarr }"

var test = eval("[" + string + "]")[0];

test(arr);
console.log(arr);
//this outputs [3,2,1]

test(arr);
console.log(arr);
//this outputs [1,2,3]

fiddle

Thanks

回答1:

Because in JavaScript, objects are pass by reference value and arrays are objects. The eval is irrelevant here. Here is code producing the same issue without eval:

var arr = [1,2,3];
var arr2 = arr; // this just sets the reference
arr2[1] = 3; // this also changes arr
arr[0] = 3; // this also changes arr2
arr; // [3, 3, 3]
arr2; // [3, 3, 3]


回答2:

Why does this happen

JavaScript kind of has a thing where it creates references instead of copies. This can be useful, and annoying:

Where is it useful?

var self = this;

is a commonly used trick to trap the scope of a function.

var elem = document.getElementById('my_element');

is a way refer to elements as variables

When does this happen?

var arr = [1, 2, 3, 4];

var arr2 = arr;    //arr2 now references arr
var arr2[1] = 'd'; //Modifies arr2 and reference

console.log(arr2); //Line 6
console.log(arr);  //Line 7

This will give us:

[1, 'd', 3, 4] (line 6)

[1, 'd', 3, 4] (line 7)

In conclusion, this is just regular behavior of JavaScript!

What should I do?

To solve this, add

var arr2 = arr.slice();

.slice() returns a new version of the array. You can write your own function to do this by:

Array.prototype.clone = function () {
    return this.slice();
}

Now we can do:

var arr = [1, 2, 3, 4];

var arr2 = arr.clone(); //  Returns cloned arr
var arr2[1] = 'd';      //  Modifies arr2

console.log(arr2); //Line 6
console.log(arr);  //Line 7

This time:

[1, 'd', 3, 4] (line 6)

[1, 2, 3, 4] (line 7)