JavaScript è un linguaggio pass-by-reference o pass-by-value?

I tipi primitivi (Number, String, ecc.) Vengono passati per valore, ma gli oggetti sono sconosciuti, perché possono essere sia passati per valore (nel caso in cui consideriamo che una variabile che contiene un object sia in realtà un riferimento all’object ) e pass-by-reference (quando consideriamo che la variabile dell’object mantiene l’object stesso).

Anche se alla fine non importa, voglio sapere qual è il modo corretto per presentare gli argomenti che superano le convenzioni. Esiste un estratto dalla specifica JavaScript, che definisce quale dovrebbe essere la semantica in merito?

È interessante in Javascript. Considera questo esempio:

 function changeStuff(a, b, c) { a = a * 10; b.item = "changed"; c = {item: "changed"}; } var num = 10; var obj1 = {item: "unchanged"}; var obj2 = {item: "unchanged"}; changeStuff(num, obj1, obj2); console.log(num); console.log(obj1.item); console.log(obj2.item); 

È sempre passato per valore, ma per gli oggetti il ​​valore della variabile è un riferimento. Per questo motivo, quando si passa un object e si cambiano i suoi membri , tali modifiche persistono al di fuori della funzione. Questo fa sembrare passare per riferimento. Ma se in realtà cambi il valore della variabile object vedrai che la modifica non persiste, dimostrando che è davvero un valore pass.

Esempio:

 function changeObject(x) { x = {member:"bar"}; alert("in changeObject: " + x.member); } function changeMember(x) { x.member = "bar"; alert("in changeMember: " + x.member); } var x = {member:"foo"}; alert("before changeObject: " + x.member); changeObject(x); alert("after changeObject: " + x.member); /* change did not persist */ alert("before changeMember: " + x.member); changeMember(x); alert("after changeMember: " + x.member); /* change persists */ 

Produzione:

 before changeObject: foo in changeObject: bar after changeObject: foo before changeMember: foo in changeMember: bar after changeMember: bar 

La variabile non “trattiene” l’object, contiene un riferimento. È ansible assegnare tale riferimento a un’altra variabile, ora entrambi fanno riferimento allo stesso object. È sempre passato per valore (anche quando quel valore è un riferimento …).

Non c’è modo di alterare il valore detenuto da una variabile passata come parametro, cosa che sarebbe ansible se JS supportasse il passaggio per riferimento.

My 2 Cents …. Questo è il modo in cui lo capisco. (Sentiti libero di correggermi se sbaglio)

È tempo di buttare via tutto ciò che sai sul valore per valore / riferimento.

Perché in JavaScript, non importa se viene passato per valore o per riferimento o altro. Ciò che conta è la mutazione vs l’assegnazione dei parametri passati in una funzione.

OK, lasciami fare del mio meglio per spiegare cosa intendo. Diciamo che hai alcuni oggetti.

 var object1 = {}; var object2 = {}; 

Quello che abbiamo fatto è “assegnazione” … Abbiamo assegnato 2 oggetti vuoti separati alle variabili “object1” e “object2”.

Ora, diciamo che ci piace object1 meglio … Quindi, “assegniamo” una nuova variabile.

 var favoriteObject = object1; 

Successivamente, per qualsiasi motivo, decidiamo che ci piace l’object 2 migliore. Quindi, facciamo semplicemente un piccolo riassegnazione.

 favoriteObject = object2; 

Non è successo niente a object1 oa object2. Non abbiamo affatto cambiato alcun dato. Tutto ciò che abbiamo fatto è stato riassegnare qual è il nostro object preferito. È importante sapere che object2 e preferredObject sono entrambi assegnati allo stesso object. Possiamo cambiare quell’object tramite una di queste variabili.

 object2.name = 'Fred'; console.log(favoriteObject.name) // logs Fred favoriteObject.name = 'Joe'; console.log(object2.name); // logs Joe 

OK, ora diamo un’occhiata alle primitive come le stringhe, per esempio

 var string1 = 'Hello world'; var string2 = 'Goodbye world'; 

Ancora una volta, prendiamo un preferito.

 var favoriteString = string1; 

Entrambe le nostre variabili FavoriteString e stringa1 sono assegnate a “Hello world”. Ora, cosa succede se vogliamo cambiare la nostra stringa preferita ??? Cosa accadrà???

 favoriteString = 'Hello everyone'; console.log(favoriteString); // Logs 'Hello everyone' console.log(string1); // Logs 'Hello world' 

Uh oh …. cosa è successo. Non è stato ansible modificare string1 modificando il PreferitoString … Perché ?? perché le stringhe sono immutabili e non le abbiamo mutate. Tutto quello che abbiamo fatto è stato “RE ASSIGN”. Preferito a una nuova stringa. Questo essenzialmente lo ha disconnesso da stringa1. Nell’esempio precedente, quando abbiamo rinominato il nostro object, non abbiamo assegnato nulla. (Beh, in realtà … l’abbiamo fatto, abbiamo assegnato la proprietà name a una nuova stringa.) Invece, abbiamo semplicemente mutato l’object che mantiene le connessioni tra le 2 variabili e gli oggetti sottostanti.

Ora, su funzioni e parametri di passaggio … Quando si chiama una funzione e si passa un parametro, ciò che si sta essenzialmente facendo è “assegnazione” a una nuova variabile, e funziona esattamente come se fosse stato assegnato semplicemente segno uguale (=).

Prendi questi esempi.

 var myString = 'hello'; // Assign to a new variable (just like when you pass to a function) var param1 = myString; param1 = 'world'; // Re assignment console.log(myString); // logs 'hello' console.log(param1); // logs 'world' 

Ora, la stessa cosa, ma con una funzione

 function myFunc(param1) { param1 = 'world'; console.log(param1); // logs 'world' } var myString = 'hello'; // Calls myFunc and assigns param1 to myString just like param1 = myString myFunc(myString); console.log(myString); // logs 'hello' 

OK, ora diamo alcuni esempi usando gli oggetti invece … prima, senza la funzione.

 var myObject = { firstName: 'Joe', lastName: 'Smith' }; // Assign to a new variable (just like when you pass to a function) var otherObj = myObject; // Let's mutate our object otherObj.firstName = 'Sue'; // I guess Joe decided to be a girl console.log(myObject.firstName); // Logs 'Sue' console.log(otherObj.firstName); // Logs 'Sue' // Now, let's reassign otherObj = { firstName: 'Jack', lastName: 'Frost' }; // Now, otherObj and myObject are assigned to 2 very different objects // And mutating one object no longer mutates the other console.log(myObject.firstName); // Logs 'Sue' console.log(otherObj.firstName); // Logs 'Jack'; 

Ora, la stessa cosa, ma con una chiamata di funzione

 function myFunc(otherObj) { // Let's mutate our object otherObj.firstName = 'Sue'; console.log(otherObj.firstName); // Logs 'Sue' // Now let's re-assign otherObj = { firstName: 'Jack', lastName: 'Frost' }; console.log(otherObj.firstName); // Logs 'Jack' // Again, otherObj and myObject are assigned to 2 very different objects // And mutating one object no longer mutates the other } var myObject = { firstName: 'Joe', lastName: 'Smith' }; // Calls myFunc and assigns otherObj to myObject just like otherObj = myObject myFunc(myObject); console.log(myObject.firstName); // Logs 'Sue', just like before 

OK, se leggi tutto il post, forse ora hai una migliore comprensione di come funzionano le chiamate di funzione in javascript. Non importa se qualcosa è passato per riferimento o per valore … Ciò che conta è l’incarico rispetto alla mutazione.

Ogni volta che si passa una variabile a una funzione, si “Assegna” a qualunque sia il nome della variabile parametro, proprio come se si fosse utilizzato il segno uguale (=).

Ricorda sempre che il segno di uguale (=) significa assegnazione. Ricorda sempre che passare un parametro a una funzione significa anche assegnare. Sono uguali e le 2 variabili sono collegate esattamente nello stesso modo.

L’unica volta che la modifica di una variabile interessa una variabile diversa è quando l’object sottostante viene mutato.

Non ha senso fare una distinzione tra oggetti e primitive, perché funziona nello stesso modo in cui se non si avesse una funzione e si usasse semplicemente il segno di uguale da assegnare a una nuova variabile.

L’unico risultato è quando il nome della variabile che si passa alla funzione è uguale al nome del parametro della funzione. Quando ciò accade, devi trattare il parametro all’interno della funzione come se fosse una variabile completamente nuova privata della funzione (perché è)

 function myFunc(myString) { // myString is private and does not affect the outer variable myString = 'hello'; } var myString = 'test'; myString = myString; // Does nothing, myString is still 'test'; myFunc(myString); console.log(myString); // logs 'test' 

Considera quanto segue:

  1. Le variabili sono puntatori ai valori in memoria.
  2. La riassegnazione di una variabile punta semplicemente il puntatore a un nuovo valore.
  3. La riassegnazione di una variabile non influirà mai su altre variabili che puntano allo stesso object

Quindi, dimentica “passa per riferimento / valore” non rimanere bloccato su “passa per riferimento / valore” perché:

  1. I termini sono usati solo per descrivere il comportamento di una lingua, non necessariamente l’effettiva implementazione sottostante. Come risultato di questa astrazione, i dettagli critici che sono essenziali per una spiegazione decente vengono persi, il che porta inevitabilmente alla situazione attuale in cui un singolo termine non descrive adeguatamente il comportamento effettivo e devono essere fornite informazioni supplementari
  2. Questi concetti non erano originariamente definiti con l’intento di descrivere javascript in particolare e quindi non mi sento in dovere di usarli quando aggiungono solo confusione.

Per rispondere alla tua domanda: i riferimenti sono passati.

 // code var obj = { name: 'Fred', num: 1 }; // illustration 'Fred' / / (obj) ---- {} \ \ 1 

 // code obj.name = 'George'; // illustration 'Fred' (obj) ---- {} ----- 'George' \ \ 1 

 // code obj = {}; // illustration 'Fred' (obj) {} ----- 'George' | \ | \ { } 1 

 // code var obj = { text: 'Hello world!' }; /* function parameters get their own pointer to * the arguments that are passed in, just like any other variable */ someFunc(obj); // illustration (caller scope) (someFunc scope) \ / \ / \ / \ / \ / { } | | | 'Hello world' 

Alcuni commenti finali:

  • È allettante pensare che le primitive siano applicate da regole speciali mentre gli oggetti non lo sono, ma le primitive sono semplicemente la fine della catena di puntatori.
  • Come ultimo esempio, considera perché un tentativo comune di cancellare un array non funziona come previsto.

 var a = [1,2]; var b = a; a = []; console.log(b); // [1,2] // doesn't work because `b` is still pointing at the original array 

L’object all’esterno di una funzione viene passato in una funzione dando un riferimento all’object esterno. Quando si usa quel riferimento per manipolare il suo object, l’object all’esterno viene quindi influenzato. Tuttavia, se all’interno della funzione hai deciso di puntare il riferimento a qualcos’altro, non hai affatto influenzato l’object all’esterno, perché tutto ciò che hai fatto è stato redirect il riferimento a qualcos’altro.

Pensalo in questo modo: è sempre un valore. Tuttavia, il valore di un object non è l’object stesso, ma un riferimento a quell’object.

Ecco un esempio, passando un numero (un tipo primitivo)

 function changePrimitive(val) { // At this point there are two '10's in memory. // Changing one won't affect the other val = val * 10; } var x = 10; changePrimitive(x); // x === 10 

Ripetendo questo con un object si ottengono risultati diversi:

 function changeObject(obj) { // At this point there are two references (x and obj) in memory, // but these both point to the same object. // changing the object will change the underlying object that // x and obj both hold a reference to. obj.val = obj.val * 10; } var x = { val: 10 }; changeObject(x); // x === { val: 100 } 

Un altro esempio:

 function changeObject(obj) { // Again there are two references (x and obj) in memory, // these both point to the same object. // now we create a completely new object and assign it. // obj's reference now points to the new object. // x's reference doesn't change. obj = { val: 100 }; } var x = { val: 10 }; changeObject(x); // x === { val: 10} 

Javascript è sempre pass-by-value , tutto è di tipo value. Gli oggetti sono valori, le funzioni membro degli oggetti sono valori stessi (ricorda che le funzioni sono oggetti di prima class in Javascript). Inoltre, per quanto riguarda il concetto che tutto in Javascript è un object , questo è sbagliato. Archi, simboli, numeri, booleani, null e indefiniti sono primitivi . A volte possono sfruttare alcune funzioni membro e le proprietà ereditate dai loro prototipi di base, ma questo è solo per comodità, non significa che siano essi stessi oggetti. Prova il seguente per riferimento

 x = "test"; alert(x.foo); x.foo = 12; alert(x.foo); 

In entrambi gli avvisi troverai il valore non definito.

In JavaScript, il tipo di valore controlla esclusivamente se quel valore sarà assegnato dalla copia valore o dalla copia di riferimento .

I valori primitivi vengono sempre assegnati / passati per copia del valore :

  • null
  • undefined
  • stringa
  • numero
  • booleano
  • simbolo in ES6

I valori composti vengono sempre assegnati / passati per copia di riferimento

  • oggetti
  • array
  • funzione

Per esempio

 var a = 2; var b = a; // `b` is always a copy of the value in `a` b++; a; // 2 b; // 3 var c = [1,2,3]; var d = c; // `d` is a reference to the shared `[1,2,3]` value d.push( 4 ); c; // [1,2,3,4] d; // [1,2,3,4] 

Nel frammento sopra, poiché 2 è una primitiva scalare, contiene una copia iniziale di quel valore e a b viene assegnata un’altra copia del valore. Quando si cambia b , non si cambia in alcun modo il valore in a .

Ma sia c che d sono riferimenti separati allo stesso valore condiviso [1,2,3] , che è un valore composto. È importante notare che né cd più “possiedono” il valore [1,2,3] – entrambi sono solo riferimenti peer uguali al valore. Quindi, quando si utilizza uno dei due riferimenti per modificare ( .push(4) ) l’effettivo valore di array condivisa, influisce solo .push(4) valore condiviso, e entrambi i riferimenti faranno riferimento al valore appena modificato [1,2,3,4] .

 var a = [1,2,3]; var b = a; a; // [1,2,3] b; // [1,2,3] // later b = [4,5,6]; a; // [1,2,3] b; // [4,5,6] 

Quando eseguiamo il compito b = [4,5,6] , non facciamo assolutamente nulla per influenzare il punto in cui a fa ancora riferimento ( [1,2,3] ). Per fare ciò, b dovrebbe essere un puntatore a a piuttosto che un riferimento array – ma non esiste tale capacità in JS!

 function foo(x) { x.push( 4 ); x; // [1,2,3,4] // later x = [4,5,6]; x.push( 7 ); x; // [4,5,6,7] } var a = [1,2,3]; foo( a ); a; // [1,2,3,4] not [4,5,6,7] 

Quando passiamo nell’argomento a , assegna una copia del riferimento a x . x e a sono riferimenti separati che puntano allo stesso valore [1,2,3] . Ora, all’interno della funzione, possiamo usare quel riferimento per mutare il valore stesso ( push(4) ). Ma quando eseguiamo l’assegnazione x = [4,5,6] , ciò non influisce in alcun modo sul punto in cui il riferimento iniziale a è puntato – punti fermi al valore (ora modificato) [1,2,3,4] .

Per passare in modo efficace un valore composto (come un array ) per copia del valore, è necessario crearne manualmente una copia, in modo che il riferimento passato non punti ancora all’originale. Per esempio:

 foo( a.slice() ); 

Valore composto (object, matrice, ecc.) Che può essere passato per copia di riferimento

 function foo(wrapper) { wrapper.a = 42; } var obj = { a: 2 }; foo( obj ); obj.a; // 42 

Qui, obj funge da wrapper per la proprietà primitiva scalare a . Quando viene passato a foo(..) , viene passata una copia del riferimento obj e impostata sul parametro wrapper . Ora possiamo usare il riferimento wrapper per accedere all’object condiviso e aggiornare la sua proprietà. Al termine della funzione, obj.a visualizzerà il valore aggiornato 42 .

fonte

Una spiegazione molto dettagliata sulla copia, il passaggio e il confronto per valore e per riferimento si trova in questo capitolo del libro “JavaScript: La guida definitiva”.

Prima di abbandonare l’argomento della manipolazione di oggetti e matrici per riferimento, è necessario chiarire un punto di nomenclatura. La frase “passa per riferimento” può avere diversi significati. Per alcuni lettori, la frase fa riferimento a una tecnica di chiamata di funzione che consente a una funzione di assegnare nuovi valori ai suoi argomenti e di rendere visibili quei valori modificati al di fuori della funzione. Questo non è il modo in cui il termine è usato in questo libro. Qui, intendiamo semplicemente che un riferimento a un object o array – non all’object stesso – è passato a una funzione. Una funzione può utilizzare il riferimento per modificare le proprietà dell’object o degli elementi dell’array. Ma se la funzione sovrascrive il riferimento con un riferimento a un nuovo object o array, tale modifica non è visibile al di fuori della funzione. I lettori che hanno familiarità con l’altro significato di questo termine potrebbero preferire dire che gli oggetti e le matrici vengono passati per valore, ma il valore che viene passato è in realtà un riferimento piuttosto che l’object stesso.

Una cosa che ancora non riesco a capire. Controlla il codice qui sotto. qualche idea?

 function A() {} A.prototype.foo = function() { return 'initial value'; } function B() {} B.prototype.bar = A.prototype.foo; console.log(A.prototype.foo()); //initial value console.log(B.prototype.bar()); //initial value A.prototype.foo = function() { return 'changed now'; } console.log(A.prototype.foo()); //changed now console.log(B.prototype.bar()); //Why still 'initial value'??? 

Passare argomenti a una funzione in JavaScript è analogo al passaggio dei parametri per il valore del puntatore in C:

 /* The following C program demonstrates how arguments to JavaScript functions are passed in a way analogous to pass-by-pointer-value in C. The original JavaScript test case by @Shog9 follows with the translation of the code into C. This should make things clear to those transitioning from C to JavaScript. function changeStuff(num, obj1, obj2) { num = num * 10; obj1.item = "changed"; obj2 = {item: "changed"}; } var num = 10; var obj1 = {item: "unchanged"}; var obj2 = {item: "unchanged"}; changeStuff(num, obj1, obj2); console.log(num); console.log(obj1.item); console.log(obj2.item); This produces the output: 10 changed unchanged */ #include  #include  struct obj { char *item; }; void changeStuff(int *num, struct obj *obj1, struct obj *obj2) { // make pointer point to a new memory location // holding the new integer value int *old_num = num; num = malloc(sizeof(int)); *num = *old_num * 10; // make property of structure pointed to by pointer // point to the new value obj1->item = "changed"; // make pointer point to a new memory location // holding the new structure value obj2 = malloc(sizeof(struct obj)); obj2->item = "changed"; free(num); // end of scope free(obj2); // end of scope } int num = 10; struct obj obj1 = { "unchanged" }; struct obj obj2 = { "unchanged" }; int main() { // pass pointers by value: the pointers // will be copied into the argument list // of the called function and the copied // pointers will point to the same values // as the original pointers changeStuff(&num, &obj1, &obj2); printf("%d\n", num); puts(obj1.item); puts(obj2.item); return 0; } 

Semantics!! Setting concrete definitions will necessarily make some answers and comments incompatible since they are not describing the same thing even when using the same words and phrases, but it is critical to get past the confusion (especially for new programmers).

First of all, there are multiple levels of abstraction that not everyone seems to grasp. Newer programmers who have learned on 4th or 5th generation languages may have difficulty wrapping their mind around concepts familiar to assembly or C programmers not phased by pointers to pointers to pointers. Pass-by-reference does not simply mean the ability to change a referenced object using a function parameter variable.

Variable : Combined concept of a symbol which references a value at a particular location in memory. This term is usually too loaded to be used alone in discussing details.

Symbol : Text string used to refer to variable (ie variable’s name).

Value : Particular bits stored in memory and referenced using variable’s symbol.

Memory location : Where a variable’s value is stored. (The location itself is represented by a number separate from the value stored at the location.)

Function parameter : Variable declared in a function definition, used for referencing variables passed to the function.

Function argument : Variable outside the function which is passed to the function by the caller.

Object variable : Variable whose basic underlying value is not the “object” itself, rather its value is a pointer (memory location value) to another location in memory where the object’s actual data is stored. In most higher-generation languages, the “pointer” aspect is effectively hidden by automatic de-referencing in various contexts.

Primitive variable : Variable whose value IS the actual value. Even this concept can be complicated by auto-boxing and object-like contexts of various languages, but the general ideas is that the variable’s value IS the actual value represented by the variable’s symbol rather than a pointer to another memory location.

Function arguments and parameters are not the same thing. Also, a variable’s value is not the variable’s object (as already pointed out by various people, but apparently ignored). These distinctions are critical to proper understanding.

Pass-by-value or Call-by-sharing (for objects) : The function argument’s value is COPIED to another memory location which is referenced by the function’s parameter symbol (regardless of whether it’s on the stack or heap). In other words, the function parameter received a copy of the passed argument’s value… AND (critical) the argument’s value IS NEVER UPDATED / ALTERED / CHANGED by the calling function. Remember, an object variable’s value is NOT the object itself, rather it is the pointer to the object, so passing an object variable by value copies the pointer to the function parameter variable. The function parameter’s value points to the exact same object in memory. The object data itself can be altered directly via the function parameter, BUT the function argument’s value IS NEVER UPDATED, so it will continue to point to the same object throughout and even after the function call (even if its object’s data was altered or if the function parameter is assigned a different object altogether). It is incorrect to conclude that the function argument was passed by reference just because the referenced object is updatable via the function parameter variable.

Call / Pass-by-reference : The function argument’s value can/will be updated directly by the corresponding function parameter. If it helps, the function parameter becomes an effective “alias” for the argument–they effectively refer to the same value at the same memory location. If a function argument is an object variable, the ability to change the object’s data is no different than the pass-by-value case since the function parameter will still point to the same object as the argument. But in the object variable case, if the function parameter is set to a completely different object, then the argument will likewise also point to the different object–this does not happen in the pass-by-value case.

JavaScript does not pass by reference. If you read closely, you will realize that all contrary opinions misunderstand what is meant by pass-by-value and they falsely conclude that the ability to update an object’s data via the function parameter is synonymous to “pass-by-value”.

Object clone/copy : A new object is created and the original object’s data is copied. This can be a deep copy or shallow copy, but the point is that a new object is created. Creating a copy of an object is a separate concept from pass-by-value. Some languages distinguish between class object and structs (or the like), and may have different behavior for passing variables of the different types. But JavaScript does not do anything like this automatically when passing object variables. But the absence of automatic object cloning does not translate to pass-by-reference.

There’s some discussion about the use of the term “pass by reference” in JS here , but to answer your question:

A object is automatically passed by reference, without the need to specifically state it

(From the article mentioned above.)

My simple way to understand this…

  • When calling a function, you are passing the content (reference or value) of the argument variables, not the the variables themselves.

     var var1 = 13; var var2 = { prop: 2 }; //13 and var2's content (reference) are being passed here foo(var1, var2); 
  • Inside the function, parameter variables, inVar1 and inVar2 , receive the contents being passed.

     function foo(inVar1, inVar2){ //changing contents of inVar1 and inVar2 won't affect variables outside inVar1 = 20; inVar2 = { prop: 7 }; } 
  • Since inVar2 received the reference of { prop: 2 } , you can change the value of the object’s property.

     function foo(inVar1, inVar2){ inVar2.prop = 7; } 

In a low level language, if you want to pass a variable by reference you have to use a specific syntax in the creation of the function:

 int myAge = 14; increaseAgeByRef(myAge); function increaseAgeByRef(int &age) { *age = *age + 1; } 

The &age is a reference to myAge , but if you want the value you have to convert the reference, using *age .

Javascript is a high level language that does this conversion for you. So, although objects are passed by reference, the language converts the reference parameter to the value. You don’t need to use & , on the function definition, to pass it by reference, neither * , on the function body, to convert the reference to the value, JS does it for you.

That’s why when you try to change an object inside a function, by replacing it’s value (ie age = {value:5} ), the change doesn’t persist, but if you change it’s properties (ie age.value = 5 ), it does.

Per saperne di più

I’ve read through these answers multiple times, but didn’t REALLY get it until I learned about the technical definition of “Call by sharing” as termed by Barbara Liskov

The semantics of call by sharing differ from call by reference in that assignments to function arguments within the function aren’t visible to the caller (unlike by reference semantics)[citation needed], so eg if a variable was passed, it is not possible to simulate an assignment on that variable in the caller’s scope. However, since the function has access to the same object as the caller (no copy is made), mutations to those objects, if the objects are mutable, within the function are visible to the caller, which may appear to differ from call by value semantics. Mutations of a mutable object within the function are visible to the caller because the object is not copied or cloned — it is shared.

That is, parameter references are alterable if you go and access the parameter value itself. On the other hand, assignment to a parameter will disappear after evaluation, and is non-accessible to the function caller.

For programming language lawyers, I’ve went through the following sections of ECMAScript 5.1 (which is easier to read than the latest edition), and go as far as asking it on the ECMAScript mailing list.

TL;DR : Everythings’re passed by value, but properties of Objects are references, and the definition of Object is creepily lacking in the standard.

Construction of Argument Lists

Section 11.2.4 “Argument Lists” says the following on producing a argument list consisting of only 1 argument:

The production ArgumentList : AssignmentExpression is evaluated as follows:

  1. Let ref be the result of evaluating AssignmentExpression.
  2. Let arg be GetValue(ref).
  3. Return a List whose sole item is arg.

The section also enumerate cases where argument list has 0 or >1 arguments.

Thus, everything’s are passed by reference.

Access of Object Properties

Section 11.2.1 “Property Accessors”

The production MemberExpression : MemberExpression [ Expression ] is evaluated as follows:

  1. Let baseReference be the result of evaluating MemberExpression.
  2. Let baseValue be GetValue(baseReference).
  3. Let propertyNameReference be the result of evaluating Expression.
  4. Let propertyNameValue be GetValue(propertyNameReference).
  5. Call CheckObjectCoercible(baseValue).
  6. Let propertyNameString be ToString(propertyNameValue).
  7. If the syntactic production that is being evaluated is contained in strict mode code, let strict be true, else let strict be false.
  8. Return a value of type Reference whose base value is baseValue and whose referenced name is propertyNameString, and whose strict mode flag is strict.

Thus, properties of Objects are always available as reference.

On Reference

It is described in section 8.7 “The Reference Specification Type”, that references are not real types in the language – they’re only used to describe the behavior of the delete, the typeof, and the assignment operators.

Definition of “Object”

It is defined in 5.1 edition that “An Object is a collection of properties”. Therefore, we can infer, that the value of the object is the collection, but as to what is the value of the collection is poorly defined in the spec, and requires a bit of effort to understand.

All function arguments in ECMAScript are passed by value. This means that the value outside of the function is copied into an argument on the inside of the function the same way a value is copied from one variable to another. If the value is primitive, then it acts just like a primitive variable copy, and if the value is a reference, it acts just like a reference variable copy. This is often a point of confusion for developers, because variables are accessed both by value and by reference, but arguments are passed only by value. When an argument is passed by value, the value is copied into a local variable (a named argument and, in ECMAScript, a slot in the arguments object). When an argument is passed by reference, the location of the value in memory is stored into a local variable, which means that changes to the local variable are refl ected outside of the function. (This is not possible in ECMAScript.)

The most succinct explanation I found was in the AirBNB style guide :

  • Primitives : When you access a primitive type you work directly on its value

    • string
    • number
    • boolean
    • nullo
    • undefined

Per esempio:

 var foo = 1, bar = foo; bar = 9; console.log(foo, bar); // => 1, 9 
  • Complex : When you access a complex type you work on a reference to its value

    • object
    • array
    • function

Per esempio:

 var foo = [1, 2], bar = foo; bar[0] = 9; console.log(foo[0], bar[0]); // => 9, 9 

Ie effectively primitive types are passed by value, and complex types are passed by reference.

sharing what I know of references in javascript

In Javascript, objects are stored as references:

 var a = { a: 1, b: 2, c: 3 }; var b = a; //bc is referencing to ac value console.log(bc) //output: 3 //changing value of bc bc = 4 //also changes the value of ac console.log(ac) //output: 4 

An easy way to determine whether something is “pass by reference” is whether you can write a “swap” function. For example, in C, you can do:

 void swap(int *i, int *j) { int t; t = *i; *i = *j; *j = t; } 

If you can’t do the equivalent of that in Javascript, it is not “pass by reference”.

I have found the extend method of the Underscore.js library very useful when I want to pass in an object as a parameter which may either be modified or replaced entirely.

 function replaceOrModify(aObj) { if (modify) { aObj.setNewValue('foo'); } else { var newObj = new MyObject(); // _.extend(destination, *sources) _.extend(newObj, aObj); } } 

I would say it is pass-by-copy –

Consider arguments and variable objects are objects created during the execution context created in the beginning of function invocation – and your actual value/reference passed into the function just get stored in this arguments + variable objects.

Simply speaking, for primitive types, the values get copied in the beginning of function call, for object type, the reference get copied.

JavaScript passes primitive types by value and object types by reference

Now, people like to bicker endlessly about whether “pass by reference” is the correct way to describe what Java et al. actually do. The point is this:

  1. Passing an object does not copy the object.
  2. An object passed to a function can have its members modified by the function.
  3. A primitive value passed to a function cannot be modified by the function. A copy is made.

In my book that’s called passing by reference.

— Brian Bi – Which programming languages are pass by reference?

There is no “pass by reference” available in JavaScript. You can pass an object (which is to say, you can pass-by-value a reference to an object) and then have a function modify the object contents:

 function alterObject(obj) { obj.foo = "goodbye"; } var myObj = { foo: "hello world" }; alterObject(myObj); alert(myObj.foo); // "goodbye" 

It’s important to note that “pass-by-reference” is a very specific term. It does not mean simply that it’s possible to pass a reference to a modifiable object. Instead, it means that it’s possible to pass a simple variable in such a way as to allow a function to modify that value in the calling context. So:

 function swap(a, b) { var tmp = a; a = b; b = tmp; //assign tmp to b } var x = 1, y = 2; swap(x, y); // x and y dont changed in method alert("x is " + x + " and y is " + y); // x is 1 and y is 2 
  1. Primitives (Number, Boolean) are passed by value.
    • Strings are immutable, so it doesn’t really matter for them.
  2. Objects are passed by reference ( the reference is passed by value)

In some case, this may be helpful to alter anArg :

 function alterMyArg(func) { // process some data // ... func(data); } alertMyArg(function(d) {anArg = d;}); 
  1. primitive type variable like string,number are always pass as pass by value.
  2. Array and Object is passed as pass by reference or pass by value based on these two condition.

    • if you are changing value of that Object or array with new Object or Array then it is pass by Value.

      object1 = {item: "car"}; array1=[1,2,3];

    here you are assigning new object or array to old one.you are not changing the value of property of old object.so it is pass by value.

    • if you are changing a property value of an object or array then it is pass by Reference.

      object1.key1= "car"; array1[0]=9;

    here you are changing a property value of old object.you are not assigning new object or array to old one.so it is pass by reference.

Codice

  function passVar(object1, object2, number1) { object1.key1= "laptop"; object2 = { key2: "computer" }; number1 = number1 + 1; } var object1 = { key1: "car" }; var object2 = { key2: "bike" }; var number1 = 10; passVar(object1, object2, number1); console.log(object1.key1); console.log(object2.key2); console.log(number1); Output: - laptop bike 10 

Simple values inside functions will not change those values outside of the function (they are passed by value), whereas complex ones will (they are passed by reference).

 function willNotChange(x) { x = 1; } var x = 1000; willNotChange(x); document.write('After function call, x = ' + x + '
'); //still 1000 function willChange(y) { y.num = 2; } var y = {num: 2000}; willChange(y); document.write('After function call y.num = ' + y.num + '
'); //now 2, not 2000

Primitives are passed by value and objects are passed by reference. This is quite different from other languages like C, VB or Delphi. I can’t say how they handle objects and primitives exactly, but I know of VB and Delphi that it can (and should) be specified.

php does something similar since version 5: all objects are passed by reference, but all primitives may be passed by reference, if preceeded by an ampersand (&). Otherwise primitives are passed by value.

So in javascript, if I pass an object X into a function via a parameter, it will still be X. If you are changing data inside the function (or any other object, but that’s not important) that new value is also available outside the function.