JavaScript是传递引​​用还是传值语言?

原始types(数字,string等)是按值传递的,但是对象是未知的,因为它们可以是值传递的(如果我们认为持有对象的variables实际上是对象的引用)和通过引用传递(当我们认为对象的variables持有对象本身)。

尽pipe最后并不重要,但我想知道传递约定的正确方法是什么。 是否有JavaScript规范的摘录,它定义了什么应该是关于这个的语义?

这在Javascript中很有趣。 考虑这个例子:

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

它总是按值传递,但对于对象来说,variables的值是一个引用。 因此,当您传递一个对象并更改其成员时 ,这些更改将持续存在于该函数之外。 这使得它看起来像通过引用。 但是如果你真的改变了对象variables的值,你将会看到这个变化不会持续下去,certificate它确实是按值传递的。

例:

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

输出:

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

variables不“持有”对象,它拥有一个引用。 您可以将该引用分配给另一个variables,现在都引用同一个对象。 它总是传递值(即使这个值是一个引用…)。

没有办法改变作为parameter passing的variables所持有的值,如果JS支持通过引用传递,这将是可能的。

我的2美分….这是我理解它的方式。 (如果我错了,请随时纠正我)

是时候抛出一切你知道的关于价值/参考的传递。

因为在JavaScript中,无论是通过值还是通过引用或其他方式传递都没关系。 重要的是将参数分配给一个函数。

好,让我尽我所能来解释我的意思。 假设你有几个对象。

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

我们所做的是“赋值”…我们已经将2个单独的空对象分配给variables“object1”和“object2”。

现在,让我们说,我们更喜欢object1 …所以,我们“分配”一个新的variables。

 var favoriteObject = object1; 

接下来,无论出于何种原因,我们认为我们更喜欢对象2。 所以,我们只是做一些重新分配。

 favoriteObject = object2; 

object1或object2什么也没有发生。 我们根本没有改变任何数据。 我们所做的只是重新分配我们最喜欢的东西。 知道object2和favoriteObject都分配给同一个对象是很重要的。 我们可以通过这些variables中的任何一个来改变对象。

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

好的,现在让我们来看看像string这样的基元

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

再次,我们select一个最喜欢的。

 var favoriteString = string1; 

我们的favoriteString和string1variables都被分配到'Hello world'。 现在,如果我们想改变我们最喜欢的String? 会发生什么???

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

呃哦….发生了什么事。 我们无法通过更改favoriteString来更改string1 …为什么? 因为string是不可变的,我们没有改变它。 我们所做的只是将“重新分配”到一个新的string。 这基本上与string1断开。 在前面的例子中,当我们重命名我们的对象时,我们没有分配任何东西。 (呃,实际上…我们做了,我们把name属性赋值为一个新的string。)相反,我们只是改变了保持2个variables和底层对象之间的连接的对象。

现在,函数和传递参数….当你调用一个函数,并传递一个参数,你实质上做的是“赋值”一个新的variables,它的工作原理是一样的,就像你简单地分配使用相等(=)标志。

以这些例子。

 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' 

现在,同样的事情,但有一个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' 

好的,现在让我们举几个使用对象的例子:首先,没有这个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'; 

现在,同样的事情,但有一个函数调用

 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 

好的,如果你阅读了整篇文章,或许你现在已经更好地理解了函数调用如何在javascript中工作。 无论是通过引用还是通过价值传递都没关系……重要的是赋值与变异。

每次将一个variables传递给一个函数,就像是使用了相等(=)符号一样,无论参数variables的名字是“赋值”。

永远记住等号(=)意味着分配。 永远记住,传递参数给一个函数也意味着分配。 它们是相同的,两个variables的连接方式完全相同。

修改variables的唯一时间影响不同的variables是基础对象发生了变化。

在对象和基元之间进行区分没有任何意义,因为它的工作原理与没有函数的方式一样,只是使用等号分配给一个新的variables。

唯一的问题是当你传入函数的variables的名字和函数参数的名字相同时。 发生这种情况时,必须将函数内部的参数看作是函数的一个私有的全新variables(因为它是)

 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' 

考虑以下几点:

  1. variables是指向内存中的值的指针
  2. 重新分配一个variables只是指向一个新值的指针。
  3. 重新分配variables不会影响指向同一对象的其他variables

所以, 忘记“通过参考/价值”不要挂在“通过参考/价值”,因为:

  1. 这些术语仅用于描述语言的行为 ,不一定是实际的底层实现。 由于这种抽象的结果,对于一个体面的解释来说至关重要的关键细节已经失去了,这必然导致目前的情况,即一个单词没有充分描述实际的行为,必须提供补充信息
  2. 这些概念最初并不是以描述javascript为目的而定义的,所以当他们只是添加到混淆中时,我不觉得有必要使用它们。

回答你的问题:指针被传递。

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

最后的一些评论:

  • 我们很容易认为, 原语是通过特殊的规则来实现的,而对象却不是,而原语只是指针链的结尾。
  • 作为最后一个例子,考虑为什么清除数组的普通尝试不能按预期工作。

 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 

对象之外的对象通过给外部对象的引用传递给一个函数。 当您使用该引用来操作其对象时,外部对象因此受到影响。 然而,如果在函数内部,你决定把引用指向别的东西,那么你根本就不会影响对象,因为你所做的全部都是把引用redirect到别的东西上。

JavaScript总是传值 ,一切都是有价值的。 对象是值,对象的成员函数本身就是值(记住,函数是Javascript中的第一类对象)。 另外,关于Javascript中所有东西都是对象的概念,这是错误的。 string,符号,数字,布尔值,零值和未定义都是原始的 。 有时候,他们可以利用从基本原型inheritance的一些成员函数和属性,但这只是为了方便,并不意味着它们本身就是对象。 尝试以下参考

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

在这两个警报中,你会发现值是未定义的。

在本书的“JavaScript:权威指南”一书中,关于复制,传递以及通过价值和参考进行比较的非常详细的解释。

在我们通过引用来处理对象和数组的主题之前,我们需要清除一个命名的点。 短语“通过引用”可以有几个含义。 对于某些读者来说,这个短语是指一个函数调用技术,它允许一个函数为它的参数赋值新的值,并且让这些修改后的值在函数之外可见。 这不是本书使用的术语。 在这里,我们的意思是指一个对象或数组的引用 – 而不是对象本身 – 传递给一个函数。 函数可以使用该引用来修改对象或数组元素的属性。 但是,如果函数用引用新对象或数组的方式覆盖引用,则该修改在函数外部是不可见的。 熟悉这个术语的其他含义的读者可能更喜欢说对象和数组是通过值传递的,但是传递的值实际上是一个引用而不是对象本身。

有一件事我仍然无法弄清楚。 检查下面的代码。 有什么想法吗?

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

像这样想:它总是按价值传递。 但是,对象的值不是对象本身,而是对该对象的引用。

这里是一个例子,传递一个数字(一个原始types)

 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 

用对象重复此操作会得到不同的结果:

 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 x and obj both hold a reference to obj.val = obj.val * 10; } var x = { val: 10 }; changeObject(x); //x === { val: 100 } 

再举一个例子:

 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中,值的types只能控制值是通过值复制还是通过引用复制来分配。

原始值始终由值复制分配/传递

  • null
  • undefined
  • 布尔
  • ES6符号

复合值始终由引用副本分配/传递

  • 对象
  • arrays
  • function

例如

 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] 

在上面的代码片段中,因为2是一个标量原语,所以a保存该值的一个初始副本,而b被赋值为另一个副本。 当改变b ,你决不会改变a的值。

但是cd都是对相同的共享值[1,2,3]单独引用,这是一个复合值。 值得注意的是, cd都没有“拥有” [1,2,3]值 – 这两个参数都是对等的。 因此,当使用任一引用修改( .push(4) )实际的共享array值本身时,它只影响一个共享值,并且两个引用都会引用新修改的值[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] 

当我们进行赋值b = [4,5,6] ,我们完全没有任何影响a仍在引用的地方( [1,2,3] )。 要做到这一点, b必须是一个指向array的引用而不是引用 – 但是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] 

当我们传入参数a ,它将a引用的副本分配给xxa是指向相同[1,2,3]值的单独引用。 现在,在函数内部,我们可以使用该引用来改变值本身( push(4) )。 但是当我们做赋值x = [4,5,6] ,这决不会影响初始引用a指向的位置 – 仍然指向(现在修改的) [1,2,3,4]值。

要通过值复制有效地传递复合值(如array ),您需要手动复制它,以便传递的引用不会指向原始。 例如:

 foo( a.slice() ); 

可以通过引用副本传递的复合值(对象,数组等)

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

在这里, obj充当标量原始属性a的包装。 当传递给foo(..)obj引用的副本被传入并设置为wrapper参数。 我们现在可以使用wrapper引用来访问共享对象,并更新其属性。 函数完成后, obj.a将看到更新的值42

资源

这里有一些关于在JS中使用术语“通过引用”的讨论,但回答你的问题:

一个对象是通过引用自动传递的,而不需要专门说明它

(从上面提到的文章。)

我发现最简洁的解释是AirBNB风格指南 :

  • 基元 :当你访问一个基元types时,你直接使用它的值

    • 布尔
    • 空值
    • 未定义

例如:

 var foo = 1, bar = foo; bar = 9; console.log(foo, bar); // => 1, 9 
  • 复杂 :当你访问一个复杂的types时,你需要引用它的值

    • 目的
    • 排列
    • function

例如:

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

即有效的原始types是通过值传递的,复杂的types是通过引用传递的。

在JavaScript中将parameter passing给函数类似于通过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 <stdio.h> #include <stdlib.h> 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.

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

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.

学到更多

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); } } 
  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)

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.

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 + '<br>'); //still 1000 function willChange(y) { y.num = 2; } var y = {num: 2000}; willChange(y); document.write('After function call y.num = ' + y.num + '<br>'); //now 2, not 2000 
  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.

  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 

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.

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: 2 //changing value of bc bc = 4 //also changes the value of ac console.log(ac) //output: 4 

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.

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

 function alterMyArg(func) { // process some data // ... func(data); } alertMyArg(function(d) {anArg = d;}); 
  • When an object is created, it exists on the heap.
  • When a primitive value is established, it lives on the stack.
  • In order to use either, you must have a variable associated with it.

With an object, the variable is essentially a pointer on the stack that points to the memory location on the heap where the object is stored. With a primitive, the variable and the value are stored together on the stack.

When you pass an object variable in JavaScript, it is always passed by Reference, meaning that the a copy of the REFERENCE is passed to the callee. If the underlying object is manipulated by the callee, the original object will be modified outside the function as well.

When you pass a stack variable in JavaScript, a copy of the actual value is passed to the callee. If the callee modifies the value it receives, the value is not modified outside of the function.