Assigning a new value to an object passed to a function in JavaScript

I am new to JavaScript (albeit C ++ experience), and today I wrote something like this:

function foo(bar) { bar = "something else"; } var x = "blah"; foo(x); alert(x); // Alerts with "blah", but I was expecting it to alert with "something else" 

I was very confused, as I watched several videos from Douglas Crockford, and I remember how he said something like "JavaScript always follows the link."

How can I explain this situation, JavaScript passes links to objects, but these links are copied. That would mean in the foo function, I assign a new link to bar , which then goes out of scope, leaving a link to the fact that x has remained untouched. Essentially, we start with:

 x ---->"blah" 

Then, when foo is called, bar refers to the same data:

 x ---->"blah" bar -----^ 

Therefore, when “something else” is assigned to bar , this happens:

 x ---->"blah" bar ---->"something else" 

Is this an accurate model of what is actually happening in JavaScript, or am I missing something else?

As an additional question, is there a way to say change the data referenced by this variable? Is this a frequently occurring situation or can it be easily avoided?

Edit:

Douglas Crockford in the video I watched says: “objects are always passed by reference, they are not passed by value”, which is true, but the arguments for functions are passed by value, it's just a link passed by value.

+7
javascript pass-by-reference pass-by-value
source share
6 answers

"JavaScript is always passed by reference" - this, as well as a [white] lie and confusion of terms. Although there is a “gray area”, I pass on to these definitions of evaluation strategies .

Here are my arguments and reasoning. If you hold a different view, make sure you can at least support it.

Call by link

Call By Reference means (for many people) that parameter assignment affects bindings in the caller.

When evaluating a package (also called "forwarding"), the function receives an implicit reference to the variable used as an argument, and not to a copy of its value. This usually means that the function can change (i.e., Assign) the variable used as an argument - something that will be visible to its caller.

This does not apply to JavaScript, as the original message is noted in the observed behavior. Re-assigning a parameter (which can be thought of as a local variable with a dynamically supplied value) does not affect any arguments provided.

Sometimes “Call By Reference” is used [confusingly] to mean “Call By Sharing” or “Call By Value [of Reference],” as discussed below; true Call By Reference is in languages ​​like C ++ and VB, but not JavaScript.

Call on [Object] Sharing

JavaScript calling conventions can be fully discussed in terms of Calling on [Object] Sharing semantics.

All JavaScript objects are values; and all primitive values ​​(which are a subset of all values) are immutable.

The semantics of a call by sharing differs from a call by reference in that the assignments for the function arguments inside the function are not displayed to the caller, for example, if a variable has been passed, it is impossible to simulate the assignment of this variable in the call area. However, since the function has access to the same object as the caller (without copying), mutations for these objects, if the objects are mutable, are visible to the caller inside the function, which may differ from the semantics of the call by value.

An example of these Shared mutations is presented in the ultrayoshi answer and can be explained simply: when an expression (such as accessing a variable) is evaluated by the object and the specified object is passed to the function, a copy / clone is not created.

Call by value [links]

While the terminology "Call By Value [of Reference]" is often used to describe behavior, it should be noted that JavaScript has no links (or "non-core" values) in the sense of Java / C #, so this terminology is subtlely misleading - at least that doesn't say Call By Reference, with different connotations, and many people understand the low explanation.

In a call by value, an argument expression is calculated, and the resulting value is bound to the corresponding variable in the function. If a function or procedure can assign values ​​to its parameters, then only its local copy is assigned — that is, [any variable] passed to the function call does not change in the call area when the function returns.

Since only a “link” to the object is transmitted (and not a copy / cloning of the specified object), semantics are simply a “sharing call”. However, I avoid this terminology in JavaScript, because then it leads to unnecessary implementation details, and also introduces a difference in how implementations convey objects against primitive values.

The description "call-by-value, where the value is a reference" is general (but should not be understood as a call by reference); Another term is call sharing.


So when I talk about convention calls in JavaScript,

I prefer to use Call By Sharing to discuss behavior, and I avoid Call By [Value / Reference] because they have too many different “values” and drag and drop unnecessary implementation details.

-3
source share

Your interpretation is in place.

First you have a variable called x , which is a reference to a string object. Let's say that the memory is 0x100. x points to 0x100 , which contains blah bytes:

 var x = "blah"; // x is 0x100 which references a string in memory 

Then you pass 0x100 to the foo function:

 function foo(bar) { bar = "something else"; } 

As everything in JavaScript is passed by value, even links , JavaScript makes a copy of this link in memory, which is now called bar inside this function:

 foo(x); // Copies the value of x (a reference) to bar 

At this moment, we have two separate variables. x and bar . Both have the same value, 0x100 . Thus, if you were to change the property of an object, then this applies to the x and bar references.

However, what you do assigns bar to point to something else:

 bar = "something else"; // Now references some other string we just created 

Now bar receives the reassignment of the link to the new line to which we just allocated memory. bar no longer has a value of 0x100 , now it has a value of a different address (say 0x500 ). x , of course, still has the value 0x100 , since bar is just a copy of x , not a reference to x .

For this reason, when you:

 alert(x); 

You will still get the original value, as this indicates x .

Second question:

is there any way to say change the data referenced by this variable? Is this a frequently occurring situation or can it be easily avoided?

Yes, just wrap it in another object. For example:

 var x = {Value: "blah"}; foo(x); 

Now we have a link to an object with the Value property, which somewhere contains a link to a string.

In foo we can do:

 bar.Value = "something else"; 

Which will affect the Value x property, since both bar and x refer to the same object, and you never changed the value of either of them.

In other words, you cannot reassign the link that you pass to the function, because you are simply redirecting the copy. However, you can change the property of the reference object, as other copies of this link point to the data that you are changing.

+5
source share

Your interpretation is correct.

You can change the values ​​of the keys in the object, which allows you to do something like gaps:

 function foo(bar) { bar.msg = "something else"; } var x = { msg: "blah" }; foo(x); alert(x.msg); 
+4
source share

Douglas Crockford in the video I watched says: “Objects are always passed by reference, they are not passed by value”, which is correct, but the arguments of functions are passed by value, it's just a link passed by value.

It is not right. What is being described is exactly called pass-by-value. JavaScript, like Java, has only bandwidth. No missing links.

You understand correctly. Each value in JavaScript is either primitive or a reference (pointer to an object). The object itself can never be a value directly. When you pass or assign a link (pointer to an object), a new copy of the pointer sees the same object as the original pointer. But they are still two different pointer variables.

+1
source share

I know that you answered your question with your editing ...

Douglas Crockford in the video I watched says: “Objects are always passed by reference, they are not passed by value”, which is true, but the arguments of functions are passed by value, it's just a link passed by value.

but due to the fact that this editing made me suddenly feel how it worked ... I admit that I struggled with this, it is a code sample and a pen that I think really demonstrate it.

 x = {}; y = x; //point y reference to same object x is pointed to console.log(x === y) //true both pointed at same object function funky(o) //pass by value a reference to object { o = null; //change reference to point to null away from object } funky(x); console.log(x)//not null still an object var myObj = { value: "Hello" }; function change(localObj) {//pass reference to object localObj.value = "Bye";//change property through the reference localObj = null;//point the reference to null away from object } console.log(x === y) //still same reference; change(myObj); console.log(myObj.value) // Prompts "Bye" console.log(myObj) //not null - its an object; x = myObj; //point x to different object console.log(x === y) //false pointed at different object; console.log(x); console.log(y); 

https://codepen.io/waynetheisinger/pres/YewMeN

0
source share

Primitive values, such as numbers, strings, etc., are not passed by reference, but only objects. For example:

 var myObj = { value: "Hello" }; function change(localObj) { localObj.value = "Bye"; } change(myObj); console.log(myObj.value) // Prompts "Bye" 
-3
source share

All Articles