12

I have lived under the assumption that there are primitive types and reference types in Javascript. On a day-to-day basis, I've never had this impact me but I was just starting to a lot more JS and wanted to update my 'thinking'. In other words, I would have betted $20 that the following would return 68

var my_obj = {};
var tmp_obj = {};

tmp_obj.my_int = 38;
my_obj.tmp_val = tmp_obj.my_int;
tmp_obj.my_int = 68;

alert('68 means reference, 38 means primitve: ' + my_obj.tmp_val);

but it returns 38.

enter image description here

Are all instances of numbers primitive types even if they exist in the context of a reference type? If y, I'm really surprised and find that odd behavior(and would be out $20). Or is my example not demonstrating what I think it is?

thx in advance

UPDATE #1

Wow, thx for all the answers. Here's a slight change which helps me a lot in understaning:

var my_obj={};
var tmp_obj={};
var my_obj_2=tmp_obj;
tmp_obj.my_int=38;
my_obj.tmp_val=tmp_obj.my_int;
tmp_obj.my_int=68
alert('68 means reference, 38 means primitve: ' + my_obj.tmp_val);   // 38
alert('68 means reference, 38 means primitve: ' + my_obj_2.my_int);  // 68
my_obj_2.my_int=78;
alert(tmp_obj.my_int); // tmp_obj is now 78 ie two way
3
  • 7
    my_obj and tmp_obj are two independent objects. Setting the value of a property of one of them won't affect the other object, no matter where the original value came from. It's the same for var a = 1; var b = a; a = 2;... b will still be 1. Commented Jan 21, 2013 at 16:51
  • Compare with: tmp_obj = my_obj; tmp_obj.my_int = 68; alert(my_obj.my_int). Commented Jan 21, 2013 at 16:51
  • 4
    @FelixKling ...and regardless of whether or not the property is primitive or reference type. Commented Jan 21, 2013 at 16:52

5 Answers 5

7

You example would work as expected if you had

     my_obj = tmp_obj;

Then, all the properties would point to the same reference since there would only be one object.

But when you write

     my_obj.tmp_val = tmp_obj.my_int;

then my_obj.tmp_val will take the value that's stored in tmp_obj.my_int but that doesn't create a new reference between the 2 objects.

Sign up to request clarification or add additional context in comments.

1 Comment

this is basically what I didn't understand correctly; thank you very much!
6

If I may use a Java-like syntax, it appears you expected the code to behave like this, where there is an integer object that has its value mutated.

tmp_obj.my_int = new Integer(38);
my_obj.tmp_val = tmp_obj.my_int;
tmp_obj.my_int.setValue(68);

Since it doesn't print 68 you conclude that integers must be a primitive type not a reference type. That doesn't necessarily follow, though. Consider this alternate interpretation:

tmp_obj.my_int = new Integer(38);
my_obj.tmp_val = tmp_obj.my_int;
tmp_obj.my_int = new Integer(68);

Here integers are reference types but my_obj.tmp_val will still contain the value 38, because assigning to an integer means overwriting references.

You can think of integers as being immutable objects. JavaScript does a very good job of presenting a unified everything-is-an-object view, so this is a better interpretation of the results than "integers are primitive types".

2 Comments

It's kind of funny to answer a question about one language with examples from another language, but you bring it to the point. Nice answer +1. (since you cannot even change the value of Number objects in JS, there really is no good way to demonstrate this in JS).
+1 for pointing out that when the assignment operator can only assign the referent and not the referee of a reference, like in Javascript, Python or Java (but contrary to C++ where pointers can be dereferenced before assignment, e.g., *p = 3;), one cannot tell whether primitive types are value types or reference types; only for composite types one can.
4

Yes, values like numbers and strings work like primitive values. They are immutable. Assigning a new value to a variable replaces the old value, it doesn't change the value that's there.

Example:

var x = 42;
var y = x; // y == 42
x = 1337; // this puts a new value in x, it doesn't change 42 to be 1337
alert(y); // it's still 42

The same works for strings:

var x = "42";
var y = x; // y == "42"
x = "1337"; // this puts a new string in x, it doesn't change "42" to be "1337"
alert(y); // it's still "42"

Also if you use object properties;

var o = {};
o.x = 42;
o.y = o.x; // o.y == 42
o.x = 1337; // this puts a new value in o.x, it doesn't change 42 to be 1337
alert(o.y); // it's still 42

How a value acts only depends on its type, not wether it's stored in a regular variable or in a property in an object.

Even if strings are implemented as an object internally, it's immutable and works as a value. Copying a string may copy a reference to an object, but the effect is that you get a separate copy, because nothing can change the string value itself.

Comments

3

I have lived under the assumption that there are primitive types and reference types in Javascript.

That's true. The only reference values are objects, though; primitive values are not mutable.

Are all instances of numbers primitive types even if they exist in the context of a reference type?

Yes. Their context is not relevant.

2 Comments

Arrays are also references.
@Barmar: arrays are also objects.
2

I believe there are two key things to understand here:

  1. Primitive values are never references
  2. JavaScript references can never be assigned to, just copied around.

Considering this code to demonstrate the first point:

var a = 10,
    b = a,
    c = {foo : 20}
    d = c.foo;

b = 20;
d = 30;
a;     // 10;
c.foo; // 20;

So, you have "slots" (variables or properties) holding primitive values, not references. Changing the value in one of those slots won't affect the others.

Considering the second point:

var a = {foo: true},
    b = a;
b.foo; // true
b.foo = false;
a.foo; // false;
b = {bar: false};
a;     // {foo: false}

Variable a contains an object, and b is initially a reference to the same object. Assigning to b.foo affects a, since b and a are pointing to the exact same object. However, those references are just like any other value stored in a given slot: when you assign something else to the slot, the reference just gets replaced with a different value. So assigning to b doesn't affect a.

3 Comments

very good point, I had to read through twice to get subtleties - so assigning can create like a hybrid object where there are parts that are part of the reference and parts that are separate.
No, I believe my explanation is confusing, I'll reword it. If you try to change b.foo before assigning something else to b, it would affect a. But after b = {bar: false};, there's no more link between the two objects. There are no hybrid objects.
ok, so similar to maybe copy-on-write in the UNIX process model.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.