After answering this question about using the style.top property of a div in jQuery's $.animate(), I started to wonder if there was a way to do it more in line with what the OP had thought (s)he could do.
The question is: can we get a direct reference to an object's property when that property is a primitive type?
For example, if you had an object called myDiv, you could get a reference to its style property, because that's an object, but is there any way to get a reference to the top property of style so that when this changes, you don't have to retrieve it again and again? (Note: I'm not saying this retrieval is computationally significant. This is just a question about what's possible, not what's good practice.)
var myDiv = document.getElementById('myDiv');
myDiv.style.top = "100px";
var myDivStyle = myDiv.style;
var myDivStyleTop = myDiv.style.top;
myDiv.style.top = "200px";
console.log(myDivStyle.top); // will print "200px"
console.log(myDivStyleTop); // will obviously print "100px"
Is there a way to reference that top property directly without going through style? My instinct is no, but JS has surprised me before, so I just wanted to make sure.
No. A variable are just simple container that can hold a value. Assigning a new value to a variable can never change the value of another variable or property.
In this regard, it doesn't matter whether the variable holds a primitive values or an object, that's just how variables work.
No there isn't. Primitives are immutable and never stored by reference.
From MDN
object reference
A link to an object. Object references can be used as if they were the objects they link to. The concept of object references arises when assigning the same object to more than one property. Each assigned property does not hold a copy of the object. Instead, they hold object references that link to the same object. In practice, this means that if the object is modified, all properties referring to the object reflect the modification.
primitive, primitive value
A data that is not an object and does not have any methods. JavaScript has 5 primitive datatypes: string, number, boolean, null, undefined. With the exception of null and undefined, all primitives values have object equivalents which wrap around the primitive values, e.g. a String object wraps around a string primitive. All primitives are immutable.
Related
I'm currently in the learning process of JavaScript and really get confused about immutable values. What I understand is, when a value is created (stings/numbers/booleans), it can never be changed.
Now my question is, the variable that I assign values, the value of that variable is changeable. I can assign new values to that variable. So why immutability is important?
Also, when I assign a new value to a variable, what happen to the previous value? Does it stay in memory and block some spaces? Does it lost its pointer from that variable? Actually what happen?
Please help me to understand what is the actual use of the concepts "Mutable" and "Immutable" in JavaScript. Thanks in advance.
What You Seem Confused About
Assignment of a variable has nothing to do with immutable or mutable objects. A variable is simply an alias: it refers to an object in memory. When you change a variable's value, all you've done is tell the compiler to stop associating that object with this variable and associate it with another object instead. Assignment does not affect the underlying object - the object never changes, you just no longer have a way to access it anymore.
Usually, when all references to an object are lost, they are garbage collected i.e. the memory allocated for the object is released and the object is lost forever. However, this also has nothing to do with the difference between immutable and mutable objects.
The Real Difference Between Immutable and Mutable Objects
Immutable objects do not modify the object in place (i.e change what it looks like) - they return a new copy of the data with the variables changed.
Mutable objects in Javascript do not return a copy, but let you change the object itself.
I liken it to the difference between array.splice() and array.slice(). splice() will change the original array by removing/inserting elements where needed - slice() will create a new array with just the elements you want. They can be made to do the same things - but one mutates the array in place, the other one creates a copy.
An immutable object is forced to always return a new copy when changed - it will not by itself be changed. A mutable object can - but does not have to - be mutated in place. Primitive types in Javascript are mostly immutable - you cannot change the form of a string once created (if you call replace on the JS string, you will receive a new string with the values you asked for replaced, not the same string with the value changed). Objects are mostly mutable: for instance you can do object[key] = value and change the object everywhere it is referenced.
tl;dr
When you change a mutable object, it is changed everywhere it is referenced. When you change an immutable object, it isn't changed at all - a new object is created, and all the old references to the object will give you the original object with nothing different about it.
Here, it says, An Object has a prototype, so there are default keys in the map. However, this can be bypassed using map = Object.create(null).
I could not understanding the meaning of map = Object.create(null).
1) What does it mean to set map.__proto__ to null?
2) In the above paragraph, what does it mean to say, default keys of map?
3) How these default keys are related to Object having a prototype?
In the above paragraph, what does it mean to say, default keys of map?
You can use an object as a string-to-value map. For example:
var map = {};
map["foo"] = "pizza";
map["year"] = 2001;
You probably expect the mapping to be initially empty. That is, for any key value, you expect the expression map[key] to return undefined, because you haven't set any values yet. However, with a normal object, map["toString"] has a value! This contradicts our expectation from the last sentence, where we expected any map[key] value to be undefined. This is what the docs mean by "default keys" -- some keys are already populated with values, even though you didn't set them.
How these default keys are related to Object having a prototype?
This is because objects inherit some properties from Object.prototype. All objects (or almost all Objects) in JavaScript have a prototype. If you ask an object for a property, and the object doesn't have that property, then it will check if its prototype has the value instead. In the toString case, the new object we created with map = {} doesn't have a toString property of its own, but its prototype, Object.prototype, does have a property named toString. Therefore, when you ask an object instance for a property named toString, you get back the toString property from the prototype.
What does it mean to set map.__proto__ to null?
The solution here is to create an object that doesn't have a prototype at all. That is, an object whose prototype is null. We can do this with Object.create(null).
In that case, when we do map = Object.create(null) and then ask for map["toString"] we really do get undefined, because the null-prototype map doesn't have a prototype to get an inherited toString property from.
map = Object.create(null).
means create an empty object which wouldn't even get properties from Object.prototype.
If you tried
Object.getPrototypeOf(map); it will return null.
Consider I have a object mainObj and I duplicating this object and saving in two other variables ObjD and ObjR.
mainObj = {x:1};
ObjR = mainObj;
ObjD = {};
mainAbjArray = Object.keys(mainObj);
for(i=0;i<mainAbjArray.length;i++){
ObjD[mainAbjArray[i]] = mainObj[mainAbjArray[i]];
}
After above execution, I have two objects when accessed gives sane data but the way of storage is different. So, how to find out if a object is saved as a reference (like ObjR) and saved with actual data (like ObjD)?
ObjR is not precisely an object, it is a name whose value is an object. That value happens to be identical to the value of the name mainObj. The value in question is {x: 1}. Anywhere in your program, writing mainObj or ObjR is semantically identical to writing {x: 1}. The former are names; the latter is a literal object. There is no way to distinguish between the two; in fact, the question is somewhat meaningless.
It is not the case that some objects are "saved with actual data" and others are "saved as reference". An object itself is just an object, the actual data comprising the object. A name is not an object, but rather can be thought of as a kind of pointer to an actual object. Names never point to other names; they point to values.
ObjR = mainObj; does not mean "set ObjR to refer to mainObj". It means "set the value of ObjR to the current value of mainObj". ObjR has no connection whatsoever with the variable mainObj.
Confusion can arise because in normal conversation we do say things like "the object ObjR". You need to keep in mind that this a sort of shorthand for saying "the object to which the variable named ObjR refers."
Consider a simpler example with numbers:
a = 1;
b = a;
Now, can I distinguish between a and b? No. Why would I want to?
You can't. Objects are always saved as a reference.
You can copy them about. mainObj and ObjR contain identical values. There is no way to distinguish them.
ObjD is just another reference to another object which you've made identical by copying all the values across.
You can distinguish between the two objects with == because they are different objects, but you can't tell how the object was created or the variable was populated.
When an object is passed into a function, the object is passed by value (although the value for an object is a reference). I am passing very large objects into my functions, but only accessing a handful of properties (6-12) from within the function. Memorywise, would it be better to only pass the properties instead of the whole object? Or would this actually create more of a memory issue if my properties are strings?
Given the two functions below, what happens memorywise? In f1, does javascript/v8 create a new object foo in memory or is it really just a pointer? Does it remain just a pointer if I access a string property or does V8 then make a copy of that string for use within the function. In f2, I assume that a completely new copy of the string foo is made for the function. Is this a correct assumption?
function f1(x) {
var y = x.foo;
}
function f2(foo) {
var y = foo;
}
var obj = {foo: "test"};
f1(obj);
f2(obj.foo);
"Memorywise, would it be better to only pass the properties instead of the whole object? Or would this actually create more of a memory issue if my properties are strings? "
That would require more memory. Doesn't really matter if they're strings, since strings are generally implemented as Reference Types as well, but for each argument, there will be a copy of the value instead of just a single copy of the Object reference.
The object reference is very light weight, so you just as just copy that instead of all individual members of the object.
Also, this will be required if you rely on mutations of the object within the function.
In your examples, there's only one property being passed (a string). If your code doesn't rely on mutations of the object itself, then there'll be no significant difference between the two.
In the example that passes the object, the only copy is the object reference. It isn't a pointer, but it is very light weight, and nothing to be concerned about.
In the example that passes the string, it would seem as though it makes a copy of the entire string, but since stings are immutable in JavaScript, implementations generally implement them as reference types as well.
Therefore it's as efficient to pass a single character string as it is to pass a 10,000 character string.
What are expando objects in javascripts?
For what purpose we need this ? Any complete example will be appreciated
I found 1 article here Javascript: The red-headed stepchild of web development
Well, in javascript, any object is an expando object. What it means is, as the article covers, that whenever you try to access a property1 it will automatically be created.
var myObj = {}; // completely empty object
myObj.myProp = 'value';
The moment you assign myProp a value, the property myProp is dynamically created, eventhough it didn't exist before. In a lot of other languages, such as C#, this is not normally possible (actually C# has just enabled expando object support as well, but that's besides the point). To access a property in a normal class in C#, you need to specify in the class that it does indeed have this property.
1 Not quite correct. See npup's comment below for clarification.
Everything except primitive types(string, number,boolean) are objects and support Key:values structure. properties(keys) can be accessed and set using the dot notation as well as the square brackets.
var myObj = {};
myObj.myProp1 = 'value1'; //works, an expando property
myObj[myProp2] = 'value2'; // doesn't work, myProp2 is an undefined name.
myObj['myProp2'] = 'value2'; // works , an expando property
myObj[2010]= 'value'; //note the key is number, still works, an expando property??
myObj.2010 = 'value'; // FAILS. to use dot notation, key must be a string
An article written in 2007 that uses document.all (as the only way to access elements)? That's a big red flag.
It is just dressing up "You can add properties to an object" with some buzzwords.
We need to be able to do this because otherwise we wouldn't be able to store data, and that would make JavaScript a pretty useless language.
(Everything is an array? No it isn't. And it iterates over an object without a hasOwnProperty wrapper. That isn't safe. Just keep away from the article, it is worse than useless)
JavaScript turns elements with specific IDs of names into expandos of the returned DOM object. It is explained here.