So I was playing around the other day just to see exactly how mass assignment works in JavaScript.
First I tried this example in the console:
a = b = {};
a.foo = 'bar';
console.log(b.foo);
The result was "bar" being displayed in an alert. That is fair enough, a and b are really just aliases to the same object. Then I thought, how could I make this example simpler.
a = b = 'foo';
a = 'bar';
console.log(b);
That is pretty much the same thing, isn't it? Well this time, it returns foo not bar as I would expect from the behaviour of the first example.
Why does this happen?
N.B. This example could be simplified even more with the following code:
a = {};
b = a;
a.foo = 'bar';
console.log(b.foo);
a = 'foo';
b = a;
a = 'bar';
console.log(b);
(I suspect that JavaScript treats primitives such as strings and integers differently to hashes. Hashes return a pointer while "core" primitives return a copy of themselves)
In the first example, you are setting a property of an existing object. In the second example, you are assigning a brand new object.
a = b = {};
a and b are now pointers to the same object. So when you do:
a.foo = 'bar';
It sets b.foo as well since a and b point to the same object.
However!
If you do this instead:
a = 'bar';
you are saying that a points to a different object now. This has no effect on what a pointed to before.
In JavaScript, assigning a variable and assigning a property are 2 different operations. It's best to think of variables as pointers to objects, and when you assign directly to a variable, you are not modifying any objects, merely repointing your variable to a different object.
But assigning a property, like a.foo, will modify the object that a points to. This, of course, also modifies all other references that point to this object simply because they all point to the same object.
Your question has already been satisfyingly answered by Squeegy - it has nothing to do with objects vs. primitives, but with reassignment of variables vs. setting properties in the same referenced object.
There seems to be a lot of confusion about JavaScript types in the answers and comments, so here's a small introduction to JavaScript's type system:
In JavaScript, there are two fundamentally different kinds of values: primitives and objects (and there is no thing like a 'hash').
Strings, numbers and booleans as well as null and undefined are primitives, objects are everything which can have properties. Even arrays and functions are regular objects and therefore can hold arbitrary properties. They just differ in the internal [[Class]] property (functions additionally have a property called [[Call]] and [[Construct]], but hey, that's details).
The reason that primitive values may behave like objects is because of autoboxing, but the primitives themselves can't hold any properties.
Here is an example:
var a = 'quux';
a.foo = 'bar';
document.writeln(a.foo);
This will output undefined: a holds a primitive value, which gets promoted to an object when assigning the property foo. But this new object is immediately discarded, so the value of foo is lost.
Think of it like this:
var a = 'quux';
new String(a).foo = 'bar'; // we never save this new object anywhere!
document.writeln(new String(a).foo); // a completly new object gets created
You're more or less correct except that what you're referring to as a "hash" is actually just shorthand syntax for an Object.
In the first example, a and b both refer to the same object. In the second example, you change a to refer to something else.
here is my version of the answer:
obj = {a:"hello",b:"goodbye"}
x = obj
x.a = "bonjour"
// now obj.a is equal to "bonjour"
// because x has the same reference in memory as obj
// but if I write:
x = {}
x.a = obj.a
x.b = obj.b
x.a = "bonjour"
// now x = {a:"bonjour", b:"goodbye"} and obj = {a:"hello", b:"goodbye"}
// because x points to another place in the memory
You are setting a to point to a new string object, while b keeps pointing to the old string object.
In the first case you change some property of the object contained in the variable, in the second case you assign a new value to the variable. That are fundamentally different things. The variables a and b are not somehow magically linked by the first assignment, they just contain the same object. That's also the case in the second example, until you assign a new value to the b variable.
The difference is between simple types and objects.
Anything that's an object (like an array or a function) is passed by reference.
Anything that's a simple type (like a string or a number) is copied.
I always have a copyArray function handy so I can be sure I'm not creating a bunch of aliases to the same array.
Related
So I was playing around the other day just to see exactly how mass assignment works in JavaScript.
First I tried this example in the console:
a = b = {};
a.foo = 'bar';
console.log(b.foo);
The result was "bar" being displayed in an alert. That is fair enough, a and b are really just aliases to the same object. Then I thought, how could I make this example simpler.
a = b = 'foo';
a = 'bar';
console.log(b);
That is pretty much the same thing, isn't it? Well this time, it returns foo not bar as I would expect from the behaviour of the first example.
Why does this happen?
N.B. This example could be simplified even more with the following code:
a = {};
b = a;
a.foo = 'bar';
console.log(b.foo);
a = 'foo';
b = a;
a = 'bar';
console.log(b);
(I suspect that JavaScript treats primitives such as strings and integers differently to hashes. Hashes return a pointer while "core" primitives return a copy of themselves)
In the first example, you are setting a property of an existing object. In the second example, you are assigning a brand new object.
a = b = {};
a and b are now pointers to the same object. So when you do:
a.foo = 'bar';
It sets b.foo as well since a and b point to the same object.
However!
If you do this instead:
a = 'bar';
you are saying that a points to a different object now. This has no effect on what a pointed to before.
In JavaScript, assigning a variable and assigning a property are 2 different operations. It's best to think of variables as pointers to objects, and when you assign directly to a variable, you are not modifying any objects, merely repointing your variable to a different object.
But assigning a property, like a.foo, will modify the object that a points to. This, of course, also modifies all other references that point to this object simply because they all point to the same object.
Your question has already been satisfyingly answered by Squeegy - it has nothing to do with objects vs. primitives, but with reassignment of variables vs. setting properties in the same referenced object.
There seems to be a lot of confusion about JavaScript types in the answers and comments, so here's a small introduction to JavaScript's type system:
In JavaScript, there are two fundamentally different kinds of values: primitives and objects (and there is no thing like a 'hash').
Strings, numbers and booleans as well as null and undefined are primitives, objects are everything which can have properties. Even arrays and functions are regular objects and therefore can hold arbitrary properties. They just differ in the internal [[Class]] property (functions additionally have a property called [[Call]] and [[Construct]], but hey, that's details).
The reason that primitive values may behave like objects is because of autoboxing, but the primitives themselves can't hold any properties.
Here is an example:
var a = 'quux';
a.foo = 'bar';
document.writeln(a.foo);
This will output undefined: a holds a primitive value, which gets promoted to an object when assigning the property foo. But this new object is immediately discarded, so the value of foo is lost.
Think of it like this:
var a = 'quux';
new String(a).foo = 'bar'; // we never save this new object anywhere!
document.writeln(new String(a).foo); // a completly new object gets created
You're more or less correct except that what you're referring to as a "hash" is actually just shorthand syntax for an Object.
In the first example, a and b both refer to the same object. In the second example, you change a to refer to something else.
here is my version of the answer:
obj = {a:"hello",b:"goodbye"}
x = obj
x.a = "bonjour"
// now obj.a is equal to "bonjour"
// because x has the same reference in memory as obj
// but if I write:
x = {}
x.a = obj.a
x.b = obj.b
x.a = "bonjour"
// now x = {a:"bonjour", b:"goodbye"} and obj = {a:"hello", b:"goodbye"}
// because x points to another place in the memory
You are setting a to point to a new string object, while b keeps pointing to the old string object.
In the first case you change some property of the object contained in the variable, in the second case you assign a new value to the variable. That are fundamentally different things. The variables a and b are not somehow magically linked by the first assignment, they just contain the same object. That's also the case in the second example, until you assign a new value to the b variable.
The difference is between simple types and objects.
Anything that's an object (like an array or a function) is passed by reference.
Anything that's a simple type (like a string or a number) is copied.
I always have a copyArray function handy so I can be sure I'm not creating a bunch of aliases to the same array.
I was reading a book about object oriented javascript and I found this:
Reference types do not store the object directly into the variable to which it is assigned, so the
object variable in this example doesn’t actually contain the object instance. Instead, it holds
a pointer (or reference) to the location in memory where the object exists. This is the primary
difference between objects and primitive values, as the primitive is stored directly in the variable.
My question is
what is the meaning of this ?
"Reference types do not store the object directly into the variable to which it is assigned, so the object variable in this example doesn’t actually contain the object instance." ??
In the image you provided you can see
var object1 = new Object();
var object2 = object1;
In this case, you have two variables that both store a reference (think of a pointer) to another place in your memory. In this place the object is stored. If you change your object via one of the references, and access it via the other one you will see it has changed.
object1.someVariable = 'asdf';
object2.someVariable = 'newValue';
console.log(object1.someVariable); // will give 'newValue'
console.log(object2.someVariable); // will also give 'newValue'
If you have scalar values, they will not store references, they will store the value itself.
Think of another example:
var primitiveString = 'asdf';
var anotherPrimitiveString = primitiveString;
Since both store the value it self, you can change one of the two strings, but the other one will still contain asdf, since they do not reference something.
anotherPrimitiveString = 'newValue';
console.log(primitiveString); // will give 'asdf'
console.log(anotherPrimitiveString); // will give 'newValue'
Here you have a jsfiddle with the explained example.
It could be clearer with an example:
var obj1 = { name: "John" };
var obj2 = obj1;
obj1 and obj2 point to the same location in memory.
It can be proved by changing name property:
obj2.name = "Bob";
console.log(obj1.name); // "Bob"
Another behaviour with primitives:
var string1 = 'string';
var string2 = string1;
string1 and string2 point to different locations in memory. So changing string2 won't affect string1
string2 = 'new string';
console.log(string1); // 'string'
You have a house. You = variable. House = value. Now, you have to prove you own that house. You get a paper, stating that you are the owner.
When you go around, you don't have to carry your house. You can just show people the paper.
House = heavy, hard to move.
Paper = small, light, easy to move.
That paper does what storing a reference does. It does not actually hold the real object, but it tells the rest of the system where it is.
In computer science in general there is two type of variables types, pointers and values.
Pointers don't hold anything but an address so the computer can find where the real value is stored, while values store the real data.
The power of pointers is you can define one value and have multiple pointers use that same value. This is a huge gain in memory management and bidirectional communication from one section of code and another.
This is an example of a pointer in javascript.
var foo = { value : 1};
var goo = foo;
goo.value = 4;
//now both goo.value and foo.value are both 4.
A value is something like this.
var foo = 2;
var goo = foo;
goo = 4;
//now foo is 2 and goo is 4.
Object1 refers to some memory location (for example 2002). Object2 is also refered to the same memory location but by referring Object1.
In js it is best to think that variables are pointers to objects & when assign directly to a variable you are not modifying any object , but pointing your variable to an object.
Let us take this example
var a= b ={}
So here a & b are pointer to same object.
Now set a.someProp = 'value'
it sets b.someProp as well since a & b point to same object
Where as storing a value in a variable is called variable initialization
What is the difference between a JS:
Object, Property and Variable ?
Sorry I'm new to JavaScript but from the way I'm understanding it is a Variable is a container to store information/data types yes ?
An object is a variable but with several different properties (whereas with a variable you have one property)? name:value pairs
a property is the building blocks of objects? is that what makes an Object an Object? because it is a variable with several name:value pairs? ........
I'm supper confused!!! are all three the same are they like interchangeable?
the only example I can think of is
Human body:
Cells
Tissues
Organs
-organs are made up of tissues
-tissues are made up of cells
-cells are tissues, basically lots of cells make up tissues and lots of tissues make up organs.
So basically organs are also cells but they are made up of a lot of cells?
I'm a bit dumb and slow when it comes to learning can somebody please enlighten me?
Explain the differences between them in very simple basic language like your explaining it to a 10 year old or something please
answers much appreciated,
Thanks :)
ps There may be a part 2 to this question
the way I'm understanding it is a Variable is a container to store information/data types yes ?
Almost. A variable is a container that stores a value. Each value is of a specific data type. Common types are number, string and Boolean.
Example:
var userID = 42;
userID is a variable. It contains the value 42. 42 is a number value, i.e. it is of type number.
A JavaScript object is a value of type object. Objects are not just simple, scalar values, they are "container" values. They can themselves contain multiple different values.
Essentially objects are key-value stores, i.e. they contain one or more keys associated with a value. These key-value pairs are called properties.
Example:
var record = {
name: 'Paul',
age: 42
};
record is a variable. It contains an object as value. The object has two properties, name and age. name holds a string value, age a number value.
When one refers to 'variable' one typically imagine a container with some memory to hold a value.
Objects are variables too but dynamically transform to containers of primitives or more-complex values upon Assignment! Complex values can be objects that hold primitive data types or even other objects such in the example below :
var SNOCounter; //gives undefined ^
SNOCounter = 3;
AccObjVar = {firstName:"John", lastName:"Smith"}; //creates an JS "object" variable with two "properties" that hold 'string' type values
AccountWrapperObj = {SNO:SNOCounter,AccountName:AccObjVar};
The dynamism of object properties is such that although AccountWrapperObj which is a JS Object holds a primitive value and Object as its original value. Replacing the AccountName property with an integer can be done by just assigning it the integer value (the properties have dynamic data types just like variables in Javascript)
AccountWrapperObj.AccountName= 'Albert Einstein'; // changes the type of AccountName from AccObjVar object type to a String
----------Extra Info ---------------
^ I am not quite clear on the memory assignment part at this stage. Link says there needs to be a bare minimum memory here for referencing the variable and actually assigning it a value.
Does declaring a variable in JavaScript with var without assignment consume memory?
A variable is a binding to a value in memory and not an object.
The item in a box analogy isn’t quite right. I think that it’s more along the lines of two tin cans connected by a string, one can being the reference(variable) and the other being the value.
I'm also new to JS, so I'll tell what's helping me here
one thing that's helping me is to think about variables as 'labels', something temporary related to execution (a metaphor from Luciano Ramalho's Fluent Python book...), and not as 'boxes', a metaphor that I've seen in a lot of tutorials
so variables are temporary, and related to execution of some function, or of the whole script (depending of where they're declared... see the difference of var, let and const for more about this)
properties, on the other hand, are related to objects, attached to the obj while it or the property exists; so you cannot create a property that's not related to an obj
let myObj = {}; // 'myObj' is the 'label' of the obj we're creating
myObj.prop = true; // we create 'prop', a property of 'myObj', using the dot notation
almost everything in JS is an obj, and objs are custom types/structures for data; functions are also objects, but they're a 'special' kind of obj, we can create and return objects with them (we can execute functions to create/return objs); so
let foo; // declaring an empty variable; the word let is related to the scope of the variable, you can use var, let or const when declaring variables
foo = function(){ return {}; }; // foo returns an empty obj
myObj = foo(); // we execute foo() so that myObj is again an empty obj
the value of a property can also be an object, so we can also do
myObj.foo = function(...args){ // receives no or more arguments
const createProps = (el, i) => { // declares a variable and defines an arrow function
this[`prop${i+1}`] = el; // uses the index of the argument to create the name of the property, with the argument value
}
args.forEach(createProps); // for each arg, create a property
}
myObj.foo('some', 'new', 'properties'); // execute the function, creating new properties in 'myObj'
above, the function that creates properties for my myObj is part of myObj, as a property...
so objects and properties have to do with data structuring, how I relate the different kinds of data in my code; and functions and variables - these 'temporary labels' - have to do with execution, doin' stuff, creating objs, and so on... both 'portions' workin' together, of course
If JavaScript will readily coerce between primitives and objects why adding properties to it results to undefined??
var a = "abc";
var b = a.length
console.log(b)//outputs 3
Does coercion allow me to assign values to primitives?If not why ?
Does coercion allow me to assign values to primitives?
Yes. The primitive is wrapped in an object, and a property is created on that. No exception will be thrown.
why adding properties to it results to undefined?
The adding itself does result in the value.
var str = "abc";
console.log(str.someProperty = 5); // 5
Yet, what you're asking for is getting a property from a primitive. This will return in undefined since the primitive is wrapped in a new wrapper object - not the one which you assigned the property on:
console.log(str.someProperty); // undefined
It only works for special properties like .length that are created with the object, or inherited ones like slice or charAt methods (see the docs for those).
If you wanted such a thing, you'd need to create the wrapper object explicitly and store it somewhere:
var strObj = new String("abc");
strObj.someProperty = 5;
console.log(strObj.someProperty); // 5
// coercion and the `toString` method will even make the object act like a string
console.log(strObj + "def"); // "abcdef"
Why don't you do it like this?
var abc=Number(3);
abc.foo="bar";
abc; //3
abc.foo; //bar
#Bergi indeed, sorry for this. I've missed the new statement. Here it is:
var abc=new Number(3);
abc.foo="bar";
abc; //3
abc.foo; //bar
At least it works just right. I don't know what else someone may need :)
primitives... coercion... blah.
I just can't understand how variables are passed, why are some passed by reference while other by value?
Example:
var a=4;
var b=a;
b=b++;
alert(a);//unmodified 4
var c=["t","ttt"];
var d=c;
d=d.sort(function(x,y){return (y.length-x.length);});
alert(c);//modified ["ttt","t"]
Where can I find a list of what variables will work like the first example and which like the second? (booleans, strings, etc... there are too many to test them all by miself)
JavaScript is always pass by value.
It's very common to say that objects in JavaScript are pass by reference, however that is not true. In a true pass by reference language, you could pass a reference to an object's reference, and have it point to another object. This is not possible in JavaScript.
Take, for example, C#. By default everything in C# is pass by value, just like JavaScript.
void foo(string s) {
s = "passbyvalue";
}
string a = "original value";
foo(a);
// a is still "original value"
However, if you alter foo to use pass by reference, the behavior changes:
void foo(ref string s) {
s = "passbyreference";
}
string a = "original value";
foo(ref a);
// a is now "passbyreference"
In JavaScript, only the first example is possible.
In JavaScript, everything is pass by value. This includes the object reference (yes, it is confusing). The reference itself is a value (it's very much like a pointer). It merely contains an id that allows the runtime to look up the object that is most likely stored in its heap. When you pass an object to a function, you are actually copying its reference into the function
It may be a seemingly small, and even anal, difference. But it's a key difference. Languages that have true pass by reference such as C# and C++ allow you to do things that are simply not possible in languages like JavaScript. The above trite example is one.
Imagine everything in JavaScript as an object. Object references are copied by value, but object properties are still used by reference. So:
var a = {};
var b = a;
b = 'Blah';
console.log(a); // Still {}
and
var a = {};
var b = a;
b.test = 'Blah';
console.log(a); // Is now {test: 'Blah'}
To simplify things a little: properties are by reference, values are by value.
Usually you can check the method on MDN. For example, the sort method's documentation states (emphasis added):
Sorts the elements of an array in place and returns the array.
The "in place" there says it will modify the array.
All primitives (for example, numbers and booleans) are passed by value; all objects are passed by reference, although some (like String objects) are immutable (although still passed by reference).
All objects get passed by reference and values by value. (technically this is not true, but it explains the behaviour)