If i am not wrong, the pointer that the variable name is using cannot change in memory, but the thing the variable points to might change.
let name = "google";
const foo = name;
console.log(foo); //prints google
name = "yahoo";
console.log(foo); //prints google again instead of yahoo
Should it not print yahoo, as the variable name's value has been changed.. Can anyone explain me this.
Another example, where its changes...
const foo = [];
foo.push("test");
console.log(foo); // outputs ["test"]
I am getting confused here, can anyone explain me this.
Your first example uses an immutable string and the second uses a mutable object.
JS strings are immutable after being declared or created, so foo is not a reference to name's value, it points to the string. You're not changing the strings, you're pointing to a different one.
The array variable points to the object and continues pointing to the same object after it's been mutated. You're still pointing to the same object, however, since const is not deep.
This also highlights a common misunderstanding with JS' const, which functions more like Java's final than C++'s const. You are declaring a variable as const, not an instance of the object, so it only prevents you from reassigning to the variable, it does not prevent you from mutating the underlying object.
From MDN:
The const declaration creates a read-only reference to a value. It does not mean the value it holds is immutable, just that the variable identifier cannot be reassigned.
This means that you can change the value assigned to a const, say by changing array or object, but cannot assign a new value to the const variable. E.g.:
Valid:
const a = [];
a.push(5);
console.log(a);
const b = {};
b['foo'] = 'bar';
console.log(b);
Invalid: This will throw error
const a = [];
a = [5];
console.log(a);
const b = {};
b = {'foo': 'bar'};
console.log(b);
Related
Is it possible in JavaScript to reassign const variable;
In C++ we can cast variable to and from const, but is it something similar possible in JavaScript;
Here I ask about
const a = 1;
unconst(a);
a = "xyz";
a === "xyz" // true
Not object properties reassignments and array push/pop;
or
let a = 1;
const(a);
a = "xyz"; // error
a === 1 // true
a is const now, something like Object.freeze for objects
No, not with standard API. See also: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/const
Constants are block-scoped, much like variables defined using the let statement. The value of a constant can't be changed through reassignment, and it can't be redeclared.
The const declaration creates a read-only reference to a value. It does not mean the value it holds is immutable—just that the variable identifier cannot be reassigned. For instance, in the case where the content is an object, this means the object's contents (e.g., its properties) can be altered.
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.
var name = 'naGeoExit';
var name = name.substring(2,5);
console.log(name); //output: Geo
Is the first name variable and the second name variable are two different variables being allocated in the different parts of the memory or value of the original variable is being changed ?
If they have the same name and are in the same scope then they're the same variable.
At line 1, there is a string in memory containing "naGeoExit". There is a variable in scope, called name that points to it.
At the second line, there is a copy of the subsequence of the string in memory. The variable name now points to that. There is no reference to the original string object, so it is garbage collected at some point.
Using the var keyword means "create a variable in the current scope (rather than the global scope)". The current scope is a closure, for example a function definition (although it could also be the global scope if you are not in a function).
It is not a syntax error to use var twice, but its purpose is to create a new variable and you should only use it once per scope. Second time round will have no effect.
Yes, the original string is unmodified. In your example, though, it's immediately available for garbage collection.
Here's an example that shows that the string is unmodified more clearly:
var n1 = 'naGeoExit';
var n2 = n1.substring(2,5);
console.log(n1); //output: naGeoExit
console.log(n2); //output: Geo
In your original code, you had only one variable called name, and you assigned the result of the substring operation to it, which is why the original string was immediately available for garbage collection. Re-declaring the same variable in the same scope has no effect. So the code:
var name = "foo";
var name = "bar";
...is exactly the same as:
var name = "foo";
name = "bar";
...and is, for that matter, exactly the same as:
var name;
name = "foo";
name = "bar";
As a beginner, working with existing code, I've come across the following:
var foo = {};
which I believe is equivalent to:
var foo = new Object();
I was under the impression that any variable was automatically an Object, so what would be the purpose of specifically coding that, rather than just declaring an empty variable:
var foo;
I was under the impression that any variable was automatically an Object
That is a mistaken impression. If you declare a variable and do not assign it a value, it is initialised to undefined (as mention in the spec and described in detail), which is not an object (it's a primitive value):
var foo;
console.log(foo); // undefined
If you were to attempt to set a property of an undefined variable you would receive a TypeError:
var foo;
foo.example = "hello"; // TypeError: Cannot set property 'example' of undefined
However, if you assign an empty object to that variable, the above code will succeed:
var foo = {}; // Now refers to an empty object (equivalent to `new Object()`)
foo.example = "hello";
console.log(foo); // '{example:"hello"}'
I believe your understanding probably stems from the common misunderstanding that "everything in JavaScript is an object". This is not true. Many things in JavaScript are objects, but primitive values are not. For example:
var a = "hello"; // String primitive, not an object
var b = new String("hello"); // String instance, object
var c = 10; // Number primitive, not an object
var d = true; // Boolean primitive, not an object
var e; // Undefined value, not an object
var f = null; // Null value, not an object
James's answer is correct. In case he's throwing too much info too quickly (refer back to it later, if so), here's a quick summary.
You are correct in this: var foo = {} and var foo = new Object() are not only equivalent, the results are identical. Only use object literals. (ignore new Object(), new Array(), etc).
var foo; does nothing other than declare a variable. It is 'undefined' by default.
var foo = new Object() also gives the new object a prototype property which can be used to manipulate object inheritance and call standard object functions defined by javascript
see here for details on how you can manipulate the object.protype:
https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/Object/prototype
I understand the following property of the javascript language:
var bar = 1;
var foo = bar;
bar = "something entirely different";
// foo is still 1
However, when trying to apply this logic to an object it seems to act differently:
var bar = {};
bar.prop = 1;
var foo = bar;
bar.prop = "something entirely different";
// foo.prop now changes to "something entirely different"
// but...
bar = "no longer an object";
// now foo remains an object with the prop property
Can someone tell me what's happening and why there is a difference?
That's correct. When you assign a variable to an object, you're really creating a second reference to that object. In the first case, what you're doing is assigning bar to point at the string foo points to, but then you change what bar points to when you reassign bar.
In the second example, you assign bar to a new object, then you point foo at that same object, then you reassign bar to a string. foo is still pointed at the same object.
Think of it like this: bar = "something" is changing what bar points to, not changing the actual object {} to a string.
This article is a fairly good explanation of what you're seeing. I'm looking for even better / more authoritative references, however.
Let's take it line by line:
var foo = bar;
All that names of objects do is hold addresses in memory. So in this statement, you are making foo hold the same memory address as bar. If for example bar was holding 0xFF, then via the assignment you would make foo also hold 0xFF.
However, keep in mind that bar and foo are two distinct objects, they happen to just hold the same address in memory.
Now, since they do happen to hold the same address in memory, mutating members of bar will also affect the members of foo because they are bound to the same object.
bar.prop = "something entirely different"; // affects foo.prop also
However, here is the key point to remember:
Assignment only changes what the name of the object is bound to, and does not affect any other objects.
In other words, the statement below made bar hold a different memory address, but this does not affect foo.
bar = "no longer an object"; // Made bar hold a different memory address
Now, explaining the quote:
Javascript is always pass by value, but when a variable refers to an object (including arrays), the "value" is a reference to the object.
Take this example:
function f(obj1, obj2)
{
obj1.prop = 10;
obj2 = {prop: 20};
}
var bar = {prop: 1};
var foo = {prop: 2};
f(bar, foo);
console.log("bar.prop: " + bar.prop + ", foo.prop: " + foo.prop);
This prints outs: bar.prop: 10, foo.prop: 2. Inside function f, obj1 holds the same memory address as bar and obj2 holds the same memory address as foo. However, only bar is affected because inside f only altering members of objects are reflected and assignment obj2 = {prop: 20}; only affects the local variable obj2 not foo.
In other words, the "value" is a reference to an object means, altering members affects the referenced object but assigning only affects the local variable.
In the first code you define the Var bar as variable.
in the second code you define it as an object.
The variables take a place in the memory;so when you define foo from bar its will be the same type as variable and will reserve a new memory location; and when you use equal operator you are replacing the data content of this variable.
The object in the second sample code on initialize will point (as pointer) to a memory location that will contain the data of this object; and when you define foo from bar its will be the same type as object and will point to the same memory location; so changing one of these two reference object value will reflect on the other one.