O JavaScript é uma linguagem de passagem por referência ou de passagem por valor?

Os tipos primitivos (Number, String, etc.) são passados ​​por valor, mas Objects são desconhecidos, porque podem ser passados ​​por valor (no caso de considerarmos que uma variável que contém um object é de fato uma referência ao object ) e passado por referência (quando consideramos que a variável para o object contém o próprio object).

Embora isso realmente não importe no final, eu quero saber qual é a maneira correta de apresentar os argumentos passando as convenções. Existe um trecho da especificação JavaScript, que define qual deve ser a semântica sobre isso?

É interessante em Javascript. Considere este exemplo:

 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 passar por valor, mas para objects o valor da variável é uma referência. Por causa disso, quando você passa um object e altera seus membros , essas alterações persistem fora da function. Isso faz com que pareça passar por referência. Mas se você realmente alterar o valor da variável de object, verá que a alteração não persiste, provando que é realmente passar por valor.

Exemplo:

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

Saída:

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

A variável não “mantém” o object, ele contém uma referência. Você pode atribuir essa referência a outra variável, agora ambos fazem referência ao mesmo object. É sempre passar por valor (mesmo quando esse valor é uma referência …).

Não há como alterar o valor mantido por uma variável passada como parâmetro, o que seria possível se JS suportasse a passagem por referência.

Meus 2 centavos … É assim que eu entendo. (Sinta-se livre para me corrigir se eu estiver errado)

É hora de jogar fora tudo o que você sabe sobre passar por valor / referência.

Porque em JavaScript, não importa se é passado por valor ou por referência ou qualquer outra coisa. O que importa é a mutação vs atribuição dos parâmetros passados ​​em uma function.

OK, deixe-me fazer o meu melhor para explicar o que quero dizer. Vamos dizer que você tenha alguns objects.

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

O que fizemos foi “atribuição” … Nós atribuímos 2 objects vazios separados às variables ​​”object1″ e “object2”.

Agora, digamos que gostamos de object1 melhor … Então, “designamos” uma nova variável.

 var favoriteObject = object1; 

Em seguida, por qualquer motivo, decidimos que gostamos mais do object 2. Então, nós simplesmente fazemos uma pequena reatribuição.

 favoriteObject = object2; 

Nada aconteceu com object1 ou object2. Nós não alteramos nenhum dado. Tudo o que fizemos foi reatribuir qual é o nosso object favorito. É importante saber que object2 e favoriteObject são ambos atribuídos ao mesmo object. Podemos mudar esse object por meio dessas variables.

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

OK, agora vamos olhar primitivos como strings por exemplo

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

Mais uma vez, escolhemos um favorito.

 var favoriteString = string1; 

Ambas as nossas variables ​​favoriteString e string1 são atribuídas a ‘Hello world’. Agora, e se quisermos mudar a nossa favoriteString ??? O que vai acontecer???

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

Uh oh …. o que aconteceu. Não foi possível alterar a string1 alterando favoriteString … Por que ?? porque as strings são imutáveis ​​e nós não a transformamos. Tudo o que fizemos foi “RE ASSIGN” favoriteString para uma nova string. Isso essencialmente desconectou da string1. No exemplo anterior, quando renomeamos nosso object, não atribuímos nada. (Bem, na verdade … nós fizemos, atribuímos a propriedade name a uma nova string.) Em vez disso, nós simplesmente alteramos o object que mantém as conexões entre as duas variables ​​e os objects subjacentes.

Agora, para funções e parâmetros de passagem …. Quando você chama uma function, e passa um parâmetro, o que você está fazendo essencialmente é “atribuição” para uma nova variável, e ela funciona exatamente como se você simplesmente tivesse atribuído usando a function sinal igual (=).

Tome estes exemplos.

 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' 

Agora, a mesma coisa, mas com uma function

 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, agora vamos dar alguns exemplos usando objects … primeiro, sem a function.

 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'; 

Agora, a mesma coisa, mas com uma chamada de function

 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 você ler todo este post, talvez agora você tenha um melhor entendimento de como as chamadas de function funcionam em javascript. Não importa se algo é passado por referência ou por valor … O que importa é atribuição vs mutação.

Toda vez que você passa uma variável para uma function, você está “Atribuindo” a qualquer que seja o nome da variável de parâmetro, como se você tivesse usado o sinal de igual (=).

Lembre-se sempre de que o sinal de igual (=) significa atribuição. Lembre-se sempre de que passar um parâmetro para uma function também significa atribuição. Eles são iguais e as duas variables ​​são conectadas exatamente da mesma maneira.

A única vez que modificar uma variável afeta uma variável diferente é quando o object subjacente é mutado.

Não faz sentido fazer uma distinção entre objects e primitivos, porque ele funciona da mesma maneira exata como se você não tivesse uma function e apenas usasse o sinal de igual para atribuir a uma nova variável.

A única pegadinha é quando o nome da variável que você passa para a function é o mesmo que o nome do parâmetro da function. Quando isso acontece, você tem que tratar o parâmetro dentro da function como se fosse uma variável inteiramente nova privada para a function (porque é)

 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' 

Considere o seguinte:

  1. Variáveis ​​são pointers para valores na memory.
  2. A reatribuição de uma variável meramente aponta esse ponteiro para um novo valor.
  3. A reatribuição de uma variável nunca afetará outras variables ​​que apontavam para o mesmo object

Então, esqueça “passar por referência / valor” não fique preso em “passar por referência / valor” porque:

  1. Os termos são usados ​​apenas para descrever o comportamento de uma linguagem, não necessariamente a implementação real subjacente. Como resultado dessa abstração, os detalhes críticos que são essenciais para uma explicação decente são perdidos, o que inevitavelmente leva à situação atual em que um único termo não descreve adequadamente o comportamento real e as informações complementares devem ser fornecidas
  2. Esses conceitos não foram originalmente definidos com a intenção de descrever o javascript em particular e, portanto, não me sinto obrigado a usá-los quando eles apenas aumentam a confusão.

Para responder à sua pergunta: pointers são passados.

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

Alguns comentários finais:

  • É tentador pensar que os primitivos são impostos por regras especiais, enquanto os objects não são, mas os primitivos são simplesmente o fim da cadeia de pointers.
  • Como último exemplo, considere por que uma tentativa comum de limpar uma matriz não funciona como esperado.

 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 

Objeto fora de uma function é passado para uma function, dando uma referência ao object externo. Quando você usa essa referência para manipular seu object, o object externo é afetado. No entanto, se dentro da function você decidiu apontar a referência para outra coisa, você não afetou o object de fora, porque tudo que você fez foi redirect a referência para outra coisa.

Pense nisso assim: é sempre passar por valor. No entanto, o valor de um object não é o object em si, mas uma referência a esse object.

Aqui está um exemplo, passando um número (um 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 

Repetir isso com um object produz resultados diferentes:

 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 } 

Mais um exemplo:

 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 passagem por valor , tudo é do tipo valor. Objetos são valores, funções-membro de objects são valores em si (lembre-se que funções são objects de primeira class em Javascript). Além disso, em relação ao conceito de que tudo no Javascript é um object , isso está errado. Strings, símbolos, números, booleanos, nulos e indefinidos são primitivos . Ocasionalmente, eles podem aproveitar algumas funções de membro e propriedades herdadas de seus protótipos de base, mas isso é apenas por conveniência, isso não significa que eles são objects em si. Tente o seguinte para referência

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

Nos dois alertas, você encontrará o valor a ser indefinido.

Em JavaScript, o tipo do valor controla apenas se esse valor será atribuído por cópia de valor ou por cópia de referência .

Os valores primitivos são sempre atribuídos / passados ​​por cópia de valor :

  • null
  • undefined
  • corda
  • número
  • boleano
  • símbolo no ES6

Valores compostos são sempre atribuídos / passados ​​por cópia de referência

  • objects
  • matrizes
  • function

Por exemplo

 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] 

No trecho acima, como 2 é uma primitiva escalar, a contém uma cópia inicial desse valor e b recebe outra cópia do valor. Ao mudar b , você não está alterando o valor em a .

Mas c e d são referências separadas para o mesmo valor compartilhado [1,2,3] , que é um valor composto. É importante notar que nem c nem d mais “possui” o valor [1,2,3] – ambos são apenas iguais referências iguais ao valor. Portanto, ao usar qualquer referência para modificar ( .push(4) ) o próprio valor da array compartilhada, ele afetará apenas o valor compartilhado e as duas referências farão referência ao valor recém-modificado [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 fazemos a atribuição b = [4,5,6] , não estamos fazendo absolutamente nada para afetar onde a ainda está fazendo referência ( [1,2,3] ). Para fazer isso, b teria que ser um ponteiro para uma referência ao invés de uma array – mas essa capacidade não existe no 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 passamos no argumento a , ele atribui uma cópia da referência a para x . x e a são referências separadas apontando para o mesmo valor [1,2,3] . Agora, dentro da function, podemos usar essa referência para alterar o próprio valor ( push(4) ). Mas quando fazemos a atribuição x = [4,5,6] , isso não afeta de forma alguma onde a referência inicial a está apontando – ainda aponta para o valor (agora modificado) [1,2,3,4] .

Para transmitir efetivamente um valor composto (como uma array ) por cópia de valor, você precisa fazer uma cópia manualmente, para que a referência passada ainda não aponte para o original. Por exemplo:

 foo( a.slice() ); 

Valor composto (object, matriz, etc) que pode ser passado por cópia de referência

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

Aqui, obj age como um wrapper para a propriedade primitiva escalar a . Quando passado para foo(..) , uma cópia da referência obj é passada e configurada para o parâmetro wrapper . Agora podemos usar a referência do wrapper para acessar o object compartilhado e atualizar sua propriedade. Depois que a function terminar, obj.a verá o valor atualizado 42 .

Fonte

Uma explicação muito detalhada sobre como copiar, passar e comparar por valor e por referência está neste capítulo do livro “JavaScript: The Definitive Guide”.

Antes de deixarmos o tópico de manipular objects e matrizes por referência, precisamos esclarecer um ponto de nomenclatura. A frase “passar por referência” pode ter vários significados. Para alguns leitores, a frase refere-se a uma técnica de invocação de function que permite que uma function atribua novos valores a seus argumentos e tenha esses valores modificados visíveis fora da function. Esta não é a maneira como o termo é usado neste livro. Aqui, queremos dizer simplesmente que uma referência a um object ou matriz – não ao object em si – é passada para uma function. Uma function pode usar a referência para modificar propriedades do object ou elementos da matriz. Mas se a function substitui a referência por uma referência a um novo object ou matriz, essa modificação não é visível fora da function. Leitores familiarizados com o outro significado deste termo podem preferir dizer que objects e matrizes são passados ​​por valor, mas o valor que é passado é na verdade uma referência em vez do próprio object.

Uma coisa que ainda não consigo descobrir. Verifique o código abaixo. Alguma ideia?

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

Passar argumentos para uma function em JavaScript é análogo à passagem de parâmetros pelo valor do ponteiro em 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.

Saber mais

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
    • número
    • boolean
    • null
    • Indefinido

Por exemplo:

 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

Por exemplo:

 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?

  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.

Code

  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.