Javascript eval 覆盖变量

Javascript Eval overwriting variable

不明白为什么下面的代码覆盖了我的 var arr。任何帮助表示赞赏。

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

谢谢

因为在JavaScript中,对象是通过引用值传递的,数组是对象。评估在这里无关紧要。这是在没有 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]

为什么会这样

JavaScript 有点像创建 references 而不是副本的地方。这可能很有用,但也很烦人:

Where is it useful?

var self = this;

是一个常用的陷阱函数范围的技巧。

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

是一种将元素作为变量引用的方法

这是什么时候发生的?

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

这会给我们:

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

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

总之,这只是 JavaScript!

的正常行为

我该怎么办?

要解决此问题,请添加

var arr2 = arr.slice();

.slice() returns 数组的 new 版本。您可以编写自己的函数来执行此操作:

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

现在我们可以做:

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

这次:

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

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