重写JS中函数内部的变量

Overwriting variables inside functions in JS

本文关键字:变量 内部 函数 JS 重写      更新时间:2023-09-26

如果这是一个愚蠢的问题,我很抱歉,我还是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`

将对象作为参数传递给函数时,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中的突变也反映在实际的数组对象中。

如果在函数中更改对象的"属性",javascript将找到引用并对其进行更改。

如果您只是更改对象的'value',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"]