Why are JavaScript primitives immutable? This seems inefficient - javascript

This is not really a question per se, but I am looking for information on why JavaScript creates a new value whenever something is reassigned.
For example, a for loop:
for(let i = 0; i < 1000; i++)
console.log(i);
I have researched that all primitives are immutable and reassigning them actually creates a new value in memory, why not overwrite the existing address?
It seems inefficient that a for loop running will create 100 unused locations when it completes when it could have used 1. It seems strange to me, but I am sure there is a valid reason for it?

Reassigning a primitive value to a variable overwrites the value at the address that the variable points to with a copy of the primitive value.
This loop will overwrite the value at the address that the variable i points to 1000 times. It will not allocate 1000 addresses in memory.
for(let i = 0; i < 1000; i++) {console.log(i);}
What is true is that if you assign to a variable a primitive value from another variable the value will be copied and both variables would point to different locations in memory. You can check it:
let a = 10;
let b = a; // the value 10 from a gets copied to b
a = 20; // the value 10 gets overwritten by 20 in a
console.log(b); // prints 10
Edit:
To answer the question directly: saying that js primitive values are immutable is another way of saying that they get assigned by value as opposed to arrays and objects that get assigned by reference (or are mutable).
Whether a new memory allocation happens or not on each assignment of a primitive value to a variable is an implementation detail, but you can trust that it is done in the most efficient way by modern js engines.

Related

Assigning one array to another javascript

So array in javascript are assigned by references so for example
let a = [1,2,3];
let b = a;
a = [];
console.log(b);
Shouldn't it print empty array as a is assigned to empty array and b and a are point to same.
I know that such behavior might seem weird. However, as other writers already mentioned, what happens is that by writing ‘a = []’ you actually assigned ‘a’ a new reference (i.e. you are not manipulating the ‘old’ array any more), and ‘b’ will hold an old reference to a memory location where ‘old’ array was initially assigned and break a relationship with ‘a’. Hence, there will now exist 2 references instead of an initial 1.

is one local scope property array for temporary results better than many global variables?

If you search for script solutions online the provided examples often declare all variables as global with var a = 'something'; var b = 123; before the function is staring an algorithm on those variables. Then within the functions sometimes more global variables are declared to hold in between results up to the point the function returns the output of whatever the algorithm is doing.
I wonder now if declaring one single variable once inside the function within an object as an array to hold all in-between results as properties is or isn't more efficient?
For example is example1 or example2 causing more memory usage when the loop would be 100.000 times?
A global function using global variables in a loop
var a = 10, b = 2.33, s = 'example1'
function do1000Times(a,b,s) {
var result = '';
for (var i = 0; i < 1000; i++) {
var half = a/2;
var multi = half*b;
result += s+' half of A multiplied by B = '+multi+"\n";
a = half;
} // end of loop
console.log(result);
return result;
} // end of function
do1000Times(a,b,s) // execute the function
vs an object with just local parameters doing the same loop
const run1000Times = {
temp : [],
result : '',
run : function(val1,val2,str) {
this.result = '';
for (this.temp.i = 0; this.temp.i < 1000; this.temp.i++) {
this.temp.half = val1/2;
this.temp.multi = this.temp.half*val2;
this.result += str+' half of A multiplied by B = '+this.temp.multi+"\n";
val1 = this.temp.half;
} // end of loop
console.log(this.result);
return this.result;
} // end of run
} // end of object
run1000Times.run(10, 2.33, 'example2') // execute run inside object
A less readable syntax but maybe faster/more efficient because of the absolute array references?
const loopXTimes = {
temp : [],
run : function(val1,val2,str,loop) {
this.temp[3] = ''; // [3] holds result
for (this.temp[0] = 0; this.temp[0] < loop; this.temp[0]++) {
// temp[0] holds iteration count
this.temp[1] = val1/2; // [1] holds result a;
this.temp[2] = this.temp[1]*val2; // [2] holds result b;
this.temp[3] += str+' half of A multiplied by B = '+this.temp[2]+"\n";
val1 = this.temp[1];
} // end of loop
console.log(this.temp[3]);
return this.temp[3];
} // end of run
} // end of object
loopXTimes.run(10, 2.33, 'example3', 1000);
The examples have no differences at all with respect to scope. Both use only local variables. The parameters are also local.
If one function use global variables and the other function use local variables there is no difference in memory usage.
To use constants in comparision < 1000 or variables < loop with loop set to 1000 makes no difference. Javascript internally optimize to whicheffer is the most effective.
To use the newer keywords const or let over var makes coding more specific and safe. It gets not faster or lessen not memory consumtion. The scope is closer with let, but it doesn't make any difference compared to a binding as far as in another object. A binding is just a binding to a variable or a constant - same speed and a memory location of same size (32 bits).
Essentially every variable have exactly the same memory usage of 32 bits. It is how Javascript is implemented to work best in general. Use (time consuming) bit operations to store 32 booleans in a variable if you must, but otherwise just let the few booleans in a program have it's use of 32 bits each. It is the size of a memory location that fit the hardware best. To store more in memory locations you also can look into typed arrays.
In a loop it is no difference to have the bindings into variables in a lot of different objects or to flatten it to have the variables directly in a loop. It is one step bindings in both cases. Javascript optimize by make local declarations to global if nessecary. It also optimize deep dot-referencing to one step bindings.
Sometimes it may be better to reference directly into objects instead of making a a lot of copies by assigning variables. Each copy (instance) requires both space and time. For example passing an object instead of its values is better. Javascript has pass by value meaning object reference is only one value to pass.
The most of time there is no use of try micro-optimize the code because the internal compiler optimization takes care of it.
Now to answer your question: is one local scope property array for temporary results better than many global variables?
Global variables stored in the window object is generally not a good practice. If the window object has to be looped (that I doubt the internal JS do) it takes more time. But the dot-operation (with .key) is still same speed independent of size or where in memory it is. Also indexing (with ['key']) is the same - actually obj['key'] equals obj.key. Everything in Javascript is Object, even arrays!
If you mean global variables in a function compared to store it in an array it has no time or space differences at all when talk about retrieving value from variable compared to indexing or referencing - it is the same. The compiler see those just as bindings to values in memory.
Compared array of size 1000 to have same data in 1000 variables in code has still no memory gains after compilation and optimization. Compiler store variables in a memory chunk (that may be seen as an array).

Why number are immutable in Javascript?

I have read the question and answer here:
javascript numbers- immutable
But it's not enough clear for me why the number (primitive type) are immutable? Just because they create a new reference but not overwrite the value?
If on each assignemt is created a new reference
var x = 5;
x = 1;
Would we have 100 times a new reference in the following loop?
while (x < 101)
{
x++;
}
Is that efficient? I think I am not seeing correctly.
I'm honestly not quite sure what kind of answer you expect since I don't quite understand what you are confused about. But here we go:
Would we have 100 times a new reference in the following loop?
Variables are just containers for values. At a low level a variable is basically just a label for a memory address or a register. E.g. variable x might point to register R1.
x++ would simply increment the number that is stored in that register by 1. Lets assume our register looked like this:
R1: 5
After incrementing it, which can be a single operation, such as ADD R1 1, we would get
R1: 6
I.e. we simple overwrote the previous value with a new one. And we do that multiple times.
Is that efficient? I think I am not seeing correctly.
Incrementing a number by one is as simple of an operation as it can get.
Sure, you could implement mutable numbers on a higher level, but it certainly wouldn't make things more efficient or simpler.
Mutability doesn't make much sense for "single value" values, because mutating such a value basically means replacing it with a different value "in place".
Mutability makes more sense for values that are composed of other values such as lists and dictionaries, where one part changes and the other stays the same.
Additionally, mutability only seems relevant when a language has reference type data types. With that I mean that multiple variables can hold a reference to the very same value of a data type. Objects are reference-type in JavaScript, which allows you to do this:
var a = {foo: 42};
var b = a;
b.foo = 21;
console.log(a);
If data types are not of a reference-type, called value-type, (which primitive values are in JavaScript), then mutability doesn't matter because it would be indistinguishable from immutability. Consider the following hypothetical scenario with a mutable, value-type number:
var a = MutableNumber(42);
var b = a; // creates a copy of MutableNumber(42) because it's a value type
a.add(1);
console.log(a, b); // would log 43, 42
In this scenario it is not possible for two variables to refer to the same mutable number value, a.add(1) is indistinguishable from assigning a new value to a (i.e. a = a + 1).
I could understand your question , the thing is , inside the while loop , everytime the x will point to the new value , whereas the old value will be made ready for garbage collection , so the memory is mantained still.
Read this for better understanding :
https://developer.mozilla.org/en-US/docs/Glossary/Mutable
So about the mutablity , your understanding is correct , the variable references the new value , the old value isn't changed , hence primitive values are immutable.
Refer: https://developer.mozilla.org/en-US/docs/Glossary/Primitive
Mutation is a change of state while numbers (the primitive type) are pure state objects. Any mutation to such a "object" state is actually a new number. Number itself is like an identifier of a mutation of bits in a cell of computer memory.
Therefore numbers are not mutable. Same as colors or characters.
It is also worth claryfining that a new number will ocupy the same memory cell as the old one for any given variable. Actually replacing the old one. Therefore there is no performance hit of any kind.
i dont understand entirely this,
var a=12;
a=45;
we can infer from ;
1.firstly interpreter allocate a chunk of memory and locate 12 to this area.
actually (a) is label of this memory area.
2.than, interpreter allocate a new memory cell and locate 45 to this area.
lastly (a) is associated with this new memory cell. The memory cell that contain 12 is destroyed by garbage collector.
Primitive values vs. references:
In JavaScript values of type boolean, undefined, null, number, symbol, string are primitive. When you assign them to a variable or pass them as an argument to a function, they always get copied.
In contrast objects have two parts to them: Object (it's data) is stored in one chunk of memory and what you assign to a variable is a reference pointing to that object. Object itself is not copied on assignment.
Because numbers are always copied when you assign them to a variable it is impossible to change a number and see that change through some other variable without actually assigning a new value to that variable.
In contrast when you change a field on an object, all variables pointing to that object will see that change.
Let's see some examples:
var a = 1;
var b = a; //This creates a new copy of value 1
console.log(a, b); // 1 1
a = 2;
console.log(a, b); // 2 1
var obj_a = {attr: 1};
var obj_b = obj_a; //This makes a new reference to the same object.
console.log(obj_a, obj_b); // {'attr': 1} {'attr': 1}
obj_b.attr = 2;
console.log(obj_a, obj_b); // {'attr': 2} {'attr': 2}
Immutable objects: immutable.js
Libraries like immutable.js provide types that combine properties of primitive types and objects: Types from immutable.js behave as ordinary objects as long as you don't change them. When you change a property of an immutable object, a new object is created and the change is only visible through that new object. The benefit is that you save space in memory and you can quickly check equality of objects by just comparing their references. You get a set of types that behave like integers but you can store more complex structures in them.

javascript: modifying second variable modifies first

I was trying to understand some javascript and found some quite unexpected behavior. Not knowing much about this language I wanted to find out what this behavior is called so that I can read about it formally.
Here's an example of the behavior:
var test={'x':2};
var test2=test;
test2.sourceLinks = [];
console.log('test',test);
console.log('test2',test2);
To my amazement, I found that modifying the 2nd variable somehow modifies the first as well. The variable "test" will also have an attribute .sourceLinks = []. Do I understand what's happening correctly, and if so, what's the formal term for this behavior?
I found that the answer to this is covered in How do I correctly clone a JavaScript object? after I posted it, although that covered more than I was asking about.
Behavior is called creating a reference. When variable assigned is an object actually it is not copied, rather the result of assignment is a new reference (pointer) to the object.
This doesn't happen with primitive types:
number,
string,
boolean,
null,
undefined.
But happens with all object types:
object,
Array,
function.
This difference is significant in javascript. When some value should be passed to another scope and it might be modified there it should be passed be reference.
function main(){
var x = 1;
modify(x);
console.log(x);//x remains 1
}
function modify(arg){
arg = 10;
}
Whereas when it is passed as a field of an object, it can be modified via reference to an object:
function main(){
var o = {x : 1};
modifyObj(o);
console.log(o);//o.x now equals 10
}
function modifyObj(arg){
arg.x = 10;
}
It's holding the reference.
When you assign object/array/function to another object/array/function it'll assign reference instead of value.
To overcome this you have to clone it
When declaring a variable in Javascript you are creating an object in memory and the variable in the scope is a pointer to that memory object.
In your example both variables (test and test2) are pointing to the same object. Hence, when you modify the the either variable pointer, it is modifying the same object in memory.

Setting one object equal to another object with the assignment operator in Javascript

I'm coming to javascript from C background. In javascript, when I use the assignment operator to assign one object to another, does it copy the values from one to the another, or do they both now point to the same data?. Or does the assignment operator do anything in this case?
function point_type()
{
this.x = 0;
this.y = 0;
}
var pnt1 = new point_type();
var pnt2 = new point_type();
pnt1.x = 4;
pnt1.y = 5;
pnt2 = pnt1;
pnt1.x = 8;
pnt2.y = 9;
In the example above, does pnt2.x now equal 8, or does it still equal 4, or does it still equal 0?
Yes, I realize I can test this myself, and I will be doing that while I wait for the community to come up with an answer. However, I'm hoping the answer to my question will go one step past just answering this one example and might shine some light on how javascript objects work and some best practices.
Follow up question:
The answer seems to be that the reference is copied. pnt2 and pnt1 now point to the same data. Is it possible to set up my object so that the values are copied? How is this usually accomplished in javascript? Clearly I don't want to set each attribute individually every time I need to copy this object.
Whenever I need to copy one object to another in JS, I just cast it to a primitive:
var newObject = JSON.stringify(oldObject);
Then when I need to use it:
var evenNewerObj = JSON.parse(newObject);
Hope this helps someone.
In JavaScript, primitive types are copied by value and reference types are copied by reference. More info here: http://docstore.mik.ua/orelly/web/jscript/ch09_03.html
It equals 8.
pnt2 = pnt1
That statement is pointing the pnt2 object to the pnt1 object so any modification you do to pnt1 will show up in pnt2.
Given the object you showed in your example, it is setting a reference to the object. If it were a primitive type (number, date) then it would copy the object.

Categories

Resources