简体   繁体   中英

Overwriting variables inside functions in JS

I apologize if this is a noob question, I'm still kind of new to JS, Why doesn't overwriting a variable work inside a function?

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`?

-- Update based on responses ---

But why does this then work?

// 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

--- Update #2 ----

Sorry just trying to wrap my mind around what is being said - why then DOESN'T this work? Isn't it basically the same as above? I'm modifying the original array just like above, not an arguments object, aren't I?

// 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`

When you are passing an object as an argument to a function, the arguments special object will hold a reference to the actual object. When you do

arguments[0] = ...

you are simply making the element at 0 refer a different object, you are not changing o . You can understand this better, if you try this

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

The output will be

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

as you can see, the element at 0 earlier was referring to o and that has been changed to string . That's it.

Instead, try this

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

you will get

{ x: 'string' }

when you print o , because, arguments[0] refers to o and the .x refers to a property in o . So you are actually changing o . This is called mutating an object.

In the same way, thisArray refers to your actual array object and when you change the element at 0, you are actually changing your actual array passed as the argument. That is why mutations in thisArray reflects in your actual array object as well.

If you change the object's 'property' in function, javascript will find the reference and change it.

If you just change object's 'value' , javascript will treat it as a local variable instead get the reference and modify it.

In first one, you didn't change the property of o, so it just overwrite argument[0], and didn't set anything to variable o. You need to return new value in function and set to o, should be like this:

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"

Or

var o = {x: 1};

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

foo();

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

Your second one is like this:

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"]

You tend to change property of array a. So it refer to a array. But in your first sample, you just change its value so it will not refer to o object.

Your update #2

You just change the "value" of a[0]. So it will not refer to array a. Similar as this:

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

function foo(){

    arguments[0] = "c";
}

foo(a[0]);

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM