覆盖JS中函数内部的变量

时间:2015-03-06 07:43:58

标签: javascript function

我很抱歉,如果这是一个noob问题,我仍然是JS的新手,为什么不覆盖函数内的变量工作?

var o = {x: 1};

function foo(){
    // Overwrite var `o` with a string
    arguments[0] = "string";
}

foo(o);

console.log(o); // Why is `o` still an object and not the string `string`?

- 根据回复更新---

但为什么会这样呢?

// Define an array literal
var a = ["a", "b"];

// Execute whatever function is passed to manipulate the array
a.execFunc = function(func){
    func(this) // Pass this array (object) to it
}

// Invoke `execFunc` function passing another function
a.execFunc(function(thisArray){
    thisArray[0] = "c"; // Change first element to "c"
})

console.log(a); // => ["c", "b", execFunc: function]: IT WORKED! a → c

---更新#2 ----

很抱歉只是试着把我的想法包围在说什么 - 为什么然后这不起作用?它与上面基本相同吗?我正在修改原始数组,而不是arguments对象,不是我吗?

// Define an array literal
var a = ["a", "b"];

// Execute whatever function is passed to manipulate the array
a.execFunc = function(func){
    func(this[0]) // Pass the first element (object property) to it
}

// Invoke `execFunc` function passing another function
a.execFunc(function(firstElement){
    console.log(firstElement = "c"); // Change first element to "c"
})

console.log(a); // => ["a", "b", execFunc: function]: first element is still `a`

2 个答案:

答案 0 :(得分:3)

当您将对象作为参数传递给函数时,arguments特殊对象将保存对实际对象的引用。当你这样做

arguments[0] = ...

您只是将元素设为0引用不同的对象,而不是更改o。如果你试试这个

,你可以更好地理解这一点
function foo() {
    console.log(arguments);
    arguments[0] = "string";
    console.log(arguments);
}

输出

{ '0': { x: 1 } }
{ '0': 'string' }

如您所见,0之前的元素指的是o,并且已更改为string。那就是它。

相反,试试这个

function foo() {
    arguments[0].x = "string";
}

你会得到

{ x: 'string' }

当您打印o时,因为arguments[0]引用o.x引用o中的属性。所以你实际上正在改变o。这称为变异对象。

以同样的方式,thisArray引用您的实际数组对象,当您将元素更改为0时,实际上您正在更改作为参数传递的实际数组。这就是为什么thisArray中的突变也反映在你的实际数组对象中。

答案 1 :(得分:1)

如果您在功能中更改了对象的' 属性,则javascript会找到该引用并进行更改。

如果您只是更改了对象的'值,则javascript会将其视为局部变量,而不是获取引用并进行修改。

在第一个中,你没有改变o的属性,所以它只是覆盖了参数[0],并没有将任何东西设置为变量o。你需要在函数中返回新值并设置为o,应该是这样的:

var o = {x: 1};

function foo(){
    // Overwrite var `o` with a string
   arguments[0] = "string";
   return arguments[0];
}

o = foo(o);

console.log(o);
//will be "string"

或者

var o = {x: 1};

function foo(){
    // Overwrite var `o` with a string
    o = "string";
}

foo();

console.log(o);
//will be "string"

你的第二个是这样的:

var a = ["a","b"];

function foo(){
    // Overwrite var `o` with a string
    arguments[0][0] = "c";
}

foo(a)

console.log(a)
//will be ["c", "b"]

您倾向于更改数组a的属性。所以它指的是一个数组。但是在第一个示例中,您只需更改其值,以便它不会引用o对象。

您的更新#2

您只需更改"值"一个[0]。所以它不会引用数组a。与此类似:

var a = ["a", "b"];

function foo(){

    arguments[0] = "c";
}

foo(a[0]);

console.log(a);
//will be ["a", "b"]