1

I was getting the pass by reference and primitive data types in javascript through the following example.

//This is pass by value example

var firstPerson = "Manish";  
var secondPerson = firstPerson;

firstPerson = "Vikash"; // value of firstPerson changed

console.log(secondPerson); // Manish
console.log(firstPerson); // Vikash



//This is the same as above example

var firstPerson = {name: "Manish"};
var secondPerson = firstPerson;

firstPerson.name = "Vikash";

console.log(secondPerson.name); // Vikash
console.log(firstPerson.name); // Vikash

In the first example, I got that I'm copying the value of firstPerson variable in secondPerson so that it holds the value and prints it. It doesn't care about reassigning any value to the firstPerson variable.

But what about the second example?

Why it is printing vikash by executing secondPerson.name even though I've copied the firstPerson = {name: "Manish"} into secondPerson?

Manish Jangir
  • 5,329
  • 4
  • 42
  • 75
  • 1
    Because you've copied the reference to the object, not the property values inside the object. Maybe check out https://en.wikipedia.org/wiki/Identity_(object-oriented_programming) – Bergi Jan 27 '16 at 06:05
  • Do you have experience with any OOP language? – Bergi Jan 27 '16 at 06:06
  • 1
    both `firstPerson` and `secondPerson` refers to the same object, which you are not changing, you are just changing a property of the object – Arun P Johny Jan 27 '16 at 06:06
  • You mean to var firstPerson = {name: "Manish"}; var secondPerson = firstPerson; is called reference and var firstPerson = "Manish"; var secondPerson = firstPerson; is called passed by value?? – Manish Jangir Jan 27 '16 at 06:08
  • 1
    Yes, objects are "reference values" (as opposed to "primitive values"), and everything is passed by value in JavaScript. – Bergi Jan 27 '16 at 06:17

3 Answers3

4

This is how I always explained this:

// 'firstPerson' holds a reference to a string "Manish".
var firstPerson = "Manish";  
// Now you state that 'secondPerson' should hold the reference
// to the same string - "Manish". Since it's a string (a primitive)
// it will be "copied" (depends on implementation), see comments.
var secondPerson = firstPerson;

// Now you say that 'firstPerson' should hold a reference to another
// string, "Vikash".
// That didn't change what the 'secondPerson' refers to, though!
firstPerson = "Vikash";

console.log(secondPerson); // Manish
console.log(firstPerson); // Vikash


// 'firstPerson' holds a reference to an object.
// **Inside** this object, 'name' holds a reference
// to a string "Manish".
var firstPerson = {name: "Manish"};
// 'secondPerson' holds a reference to the same object.
var secondPerson = firstPerson;
// Now you say that the 'name' inside this object should refer
// to another string, "Vikash".
// **That didn't change** what 'firstPerson'
// or 'secondPerson' refers to, though.
firstPerson.name = "Vikash";

console.log(secondPerson.name); // Vikash
console.log(firstPerson.name); // Vikash

You could represent this in this diagram:

// First example
firstPerson    -----> "Manish"
                   |
secondPerson   ----|

// First example after the re-assigment:
firstPerson    -----> "Manish"

secondPerson   -----> "Vikash"

// Second example
firstPerson    -----> { name:    -----> "Manish" }
                   |
secondPerson   ----|

// Second example after re-assignment:
firstPerson    -----> { name:    -----> "Vikash" }
                   |
secondPerson   ----|   <--- this arrow didn't change!

Note how the arrows change after reassignments.

kamituel
  • 34,606
  • 6
  • 81
  • 98
  • @Bergi If only I could pick some custom colours, it'd be a masterpiece! ;) – kamituel Jan 27 '16 at 06:21
  • Except that saying *firstPerson* and *secondPerson* refer to the same string is confusing. The value is always copied, but for an object the value is a reference, whereas for primitives it's the primitive value. Also, you assigned "Vikash" to *firstPerson*, not *secondPerson*. – RobG Jan 27 '16 at 06:29
  • @RobG: One could argue that in the space of string values there is only a single, immutable string with that sequence of letters. – Bergi Jan 27 '16 at 06:35
  • @RobG your comment got me thinking. Conceptually, I think you're right and my answer is indeed a bit confusing. This is interesting though: https://bugs.chromium.org/p/v8/issues/detail?id=2869. – kamituel Jan 27 '16 at 06:36
  • @RobG So I did a little experiment in latest Chrome, something like: `var s1 = 's'; var s2 = s1; var s3 = s1; ...` (up to `s15`). When executed, in heap allocations, I see "s" once under a "(string)" in constructors list, and below, all "s1 ... s15" are listed as "retainers". – kamituel Jan 27 '16 at 06:57
  • 1
    @kamituel—it doesn't matter how implementations actually do it, the [*spec says*](http://www.ecma-international.org/ecma-262/6.0/index.html#sec-assignment-operators) use [*GetValue*](http://www.ecma-international.org/ecma-262/6.0/index.html#sec-getvalue) to return the value (which is either a primitive or reference). Implementations are free to do what they want, as long as they behave as if conforming. – RobG Jan 27 '16 at 07:32
  • @RobG - correct. I wasn't saying you're wrong (actually, I did say the opposite :P) it was just an observation. – kamituel Jan 27 '16 at 07:46
0

In JavaScript Objects are reference types while strings "feel" like reference types somehow (don't forget strings are immutable!). So when you do

var firstPerson = "Manish";  
var secondPerson = firstPerson;

secondPerson has the value "Manish". When you then do

firstPerson = "Vikash"; 

you are creating a new string and firstPerson will have the new string as its value. So secondPerson is not changed at all.

I like the following quote from "JavaScript - The Definitive Guide":

What about strings? A string can have an arbitrary length, so it would seem that strings should be reference types. In fact, though, they are usually considered to be primitive types in JavaScript simply because they are not objects. Strings don't actually fit into the primitive versus reference type dichotomy. We'll have more to say about strings and their behavior a little later.

On the same link you find at 11.2.2. Copying and Passing Strings a great description:

As mentioned earlier, JavaScript strings don't fit neatly into the primitive type versus reference type dichotomy. Since strings are not objects, it is natural to assume that they are primitive. If they are primitive types, then by the rules given above, they should be manipulated by value. But since strings can be arbitrarily long, it would seem inefficient to copy, pass, and compare them byte by byte. Therefore, it would also be natural to assume that strings are implemented as reference types.

Instead of making assumptions about strings, suppose we write some JavaScript code to experiment with string manipulation. If strings are copied and passed by reference, we should be able to modify the contents of a string through the reference stored in another variable or passed to a function.

When we set out to write the code to perform this experiment, however, we run into a major stumbling block: there is no way to modify the contents of a string. The charAt( ) method returns the character at a given position in a string, but there is no corresponding setCharAt( ) method. This is not an oversight. JavaScript strings are intentionally immutable -- that is, there is no JavaScript syntax, method, or property that allows you to change the characters in a string.

Since strings are immutable, our original question is moot: there is no way to tell if strings are passed by value or by reference. We can assume that, for efficiency, JavaScript is implemented so that strings are passed by reference, but in actuality it doesn't matter, since it has no practical bearing on the code we write.

In your second example both variables are referencing the same object. If you now change this object through any of the two variables you are still changing the same object. Assigning objects is always by reference and never by value!!!

Conclusion: Although strings are often mentioned to be a primitive type they most probably feel or are implemented as a reference type. It's actually like in Java, but in Java Strings are explicitly reference types!

Nabi
  • 2,536
  • 1
  • 16
  • 18
  • 1
    By the way strings are primitives data types as I've read on https://developer.mozilla.org/en-US/docs/Web/JavaScript/Data_structures – Manish Jangir Jan 27 '16 at 06:21
  • You're correct @ManishJangirBlogaddition.com (and this answer gets it wrong) - strings are primitives. It's easy to see that: `var s = 'abc'; s.propA = 'xyz'; console.log(s.propA)` - it'll print `undefined`. – kamituel Jan 27 '16 at 06:24
  • @kamituel I updated my answer to point out better what I meant. Of course, Strings are primitives according to the ECMAScript spec, see http://www.ecma-international.org/ecma-262/5.1/#sec-4.3.16 However, i'm not sure if JavaScripts engined really copy by value when you do string assignments. Think of a very long string that you assign to another variable. This would cause the long string blocking memory twice. – Nabi Jan 27 '16 at 06:58
-1

Assignment makes a copy of the value only if it's a primitive type (like Number, Boolean, etc...). Otherwise, assignment just copies a reference to the same object (Object, Array, etc...). A new object is not created with assignment.

Reference

An assignment does not create a copy/clone/duplicate of an object.

Community
  • 1
  • 1
Kaushik
  • 2,072
  • 1
  • 23
  • 31
  • The first sentence of this answer is not 100% correct, because in case of the primitive type "string" it depends on the implementation of the JavaScript engine if the value is copied or if its reference is used for string assignments. See my answer below, which mentions the references for my claim. So a string is something special... – Nabi Jan 28 '16 at 09:58
  • @Nabi You're right. If you're assigning variables then it will be reference type and if you're assigning then it will allocate memory first time. :P – Kaushik Jan 28 '16 at 10:06
  • 1
    No, that's not what I meant. In case of strings it depends on the JavaScript implementation. The implementation can and most probably does assign the reference without doing a second memory allocation (think of large strings...). JavaScript - The Definitive Guide gives you a good hint about this, see http://docstore.mik.ua/orelly/webprog/jscript/ch11_02.htm: "We can assume that, for efficiency, JavaScript is implemented so that strings are passed by reference, but in actuality it doesn't matter, since it has no practical bearing on the code we write." (strings are immutable anyway...) – Nabi Jan 28 '16 at 10:16