var foo = {unique_prop: 1}, bar = {unique_prop: 2}, object = {};
object[foo] = 'anu';
console.log(object[bar]);
The above code outputs "anu".
toString method typecast the non-string object into string object.
In the above code object[bar] outputs the value as 'anu'.
Document says 'since both foo and bar are converted to the same string'
I can't able to understand the java script toString method on this code.
can anybody please explain how it works?
When you use foo's value as a property name, it calls toString on the foo like object[foo.toString()] = 'anu', which if not overridden, will return the same value for every object, which is '[object Object]'
So actually you have a property which name is '[object Object]'.
Below console.logs will assure that you have a property with name '[object Object]'.
var foo = {unique_prop: 1};
var object = {};
object[foo] = 'anu';
console.log(`foo.toString() - ${foo.toString()}`);
console.log(`object.toString() - ${object.toString()}`);
console.log(`object.toString() === foo.toString() ? - ${object.toString() === foo.toString()}`);
for(var prop in object) {
console.log(prop);
}
Related
While practising few examples , I encountered the following example :
var foo = {unique_prop: 1};
var bar = {unique_prop: 2};
var object = {};
object[foo] = 'value';
alert(object[bar]);
where two objects foo and bar are created . I am not getting how alert(object[bar]); is "value".
Whats the link here between foo and bar.
Also, a slight variation would give the output as "undefined" as the example below.
var foo = {unique_prop: 1};
var bar = {unique_prop: 2};
var object = {};
object["foo"] = 'value';
alert(object[bar]);
By default , the [] notation can use the strings right , arent ["some_property"] and [some_property] the same?
When using square bracket notation, anything inside the square brackets is converted into a string. Then that string is used to look for a property called the same thing.
var foo = {unique_prop: 1};
var bar = {unique_prop: 2};
var object = {};
object[foo] = 'value';
// foo is an object, so it's automatically turned into the string "[object Object]"
// so the above code is equivalent to `object["[object Object]"] = 'value';`
alert(object[bar]);
// bar is also an object, so is converted into the same string
// the above code is also equivalent to `alert(object["[object Object]"]);` which of course accesses that same value
var blah = "not blah";
object.blah = 1;
object["blah"] = 1;
object[blah];
// a variable is used.
// therefore the value of that variable is what the assessor is looking for, not the name of the variable.
// so the above code is equivalent to `object["not blah"];`.
An object's keys can only be strings*, so when you access an object's property using value which is not a string, it gets converted to a string.
In ECMAScript 6 you can use Map, which is similar to objects, but you can use any value as a key. Example:
const foo = {unique_prop: 1}
const bar = {unique_prop: 2}
const map = new Map()
map.set(foo, 'value')
console.log(map.get(bar)) // undefined
* In ECMAScript 6 you can also use symbols, but that's not relevant here.
I have the following code snippet below:
var obj = new Object();
var foo = new Object();
var bar = new Object();
obj[foo] = 'hello';
obj[bar] = 'hi'
console.log (obj[foo])
It prints "hi". Why is this?
Objects in JS can have string keys only. When you do obj[foo] actualy you do obj[foo.toString()].
Your code will be
obj["[object Object]"] = 'hello';
obj["[object Object]"] = 'hi'
console.log (obj["[object Object]"])
Objects need a string as reference. Any variable used as key is casted to string with the prototype toString and here you get for this '[object Object]', which is used as key.
var obj = new Object(),
foo = new Object(),
bar = new Object();
obj[foo] = 'hello';
obj[bar] = 'hi'
console.log (obj[foo]);
console.log('' + foo); // force object to use toString() method
console.log (obj['[object Object]']);
you are assigning the object obj with keys which are objects (foo & bar).
When keys given to object are objects themselves then the following is assigned as the key value
[object Object]
this simply means that your 1st assignment
obj[foo] = 'hello'
created key [object Object] and made its value "hello";
then your second assignment did the same, but since the key [object Object] is already present, the previous value got overridden with "hi".
Now when you try to access the property of obj with foo or bar or any other object, you are actually doing
obj["[object Object]"]
You're defining foo as an object, and bar as an object. When you assign them to the original object (obj), you're basically saying this:
obj["Object"] = 'hello';
obj["Object"] = 'hi';
console.log(obj["Object"]); //Will be the last object.
Keys need to be string types. If they're not a string, they will be converted to a string. In the cast of Object() to a string, they'll be turned into [object Object]. Check out this answer for an alternatitve way to override toString()'s functionality to return the object's name, or a unique identifer for the key you're trying to create.
To see this in action, let's do this:
var obj = new Object();
var foo = new Object();
var bar = new Object();
obj[foo] = 'hello';
console.log(obj);
/* Shows:
{
"[object Object]": "hello"
}
*/
obj[bar] = 'hi';
console.log(obj);
/* Shows:
{
"[object Object]": "hi"
}
*/
console.log(obj[foo]); //Will show hi
console.log(obj['[object Object]']); //Essentially the same thing
I have not used the new object constructor on javascript yet, since it is not my preferred language, but the mistake is most likely obvious, you have not assigned anything on your "foo" and "bar" variables, so regardless, their values will be the same, which is the initial value upon declaration of the object without any assignment. What's happening is you are assigning second value on top of your first, which applies to the "obj" array's element.
You are using objects as property-names in your object obj. Property names are strings, therefore your objects are stringified to [object Object]. As both objects are stringified to the same name, bar replaces foo.
The result looks like this:
{
"[object Object]": "hi"
}
I have an object named result which is composed of two objects like :
const a = {bar: {baz: 2}};
var b = {foo: 1};
var result = Object.assign({}, a, b);
console.log(result, a, b);
// result -> {bar: {baz: 2}, foo: 1}
// a -> {bar: {baz: 2}}
// b -> {foo: 1}
Now, I am changing the bar property of the result object like:
result.bar.baz = 3;
result.foo = 4;
console.log(result, a, b);
// result -> {bar: {baz: 3}, foo: 4}
// a -> {bar: {baz: 3}} intresting part
// b -> {foo: 1} intresting, too!
(You can copy and paste code to javascript console in order to see the result for both cases by the way)
There are two weird things here. First one is that I am changing the resulting object's property, but constant object a's property changes, too. Even if first one is the case with Object.assign function, how can I change the constant variable? Let's say this is the case despite const variable mutation, then why the change in property foo does not reflect to the object b?
I came with that because I generally use Object.assign to copy objects, but this is pretty weird issue with that function I guess. Any ideas about the case? Thank you.
Declaring a variable with const only prevents it from being changed to another value. It doesn't prevent the data referenced by that value to change.
const foo = {prop: 'bar'};
foo.prop = 'baz'; // Works well
foo = 'baz'; // TypeError: invalid assignment to const `foo'
If you want to prevent an object from being changed, you can freeze it.
Object.freeze(foo);
foo.prop = 'buz'; // TypeError: "prop" is read-only
However, that will only affect own properties. If the value of one of these is another object, it won't become frozen.
This is what happens with Object.assign too. It only copies own properties, and if their value is an object, it won't "clone" it. That is, the references will still be the same, and changes will be reflected.
If you want to deeply clone an object, see What is the most efficient way to clone an object?
Object.assign will work but with the added gotcha that if any of the properties you are assigning from contain an object as a value it does not create a copy of that object, so the references do not change, the property in the created object will point to that same nested object.
Also constant in javascript can be deceiving, you can add and remove properties from a 'const' object as long as you don't try to reassign it to a new object or a different primitive.
Same will occur with arrays, you can create a 'const' array but push pop off of it.
https://jsfiddle.net/eu9yg37s/6/ just something I was messing around in to attempt to display what I mean.
const a = {bar: {baz: 2}};
var b = {foo: 1};
// Example of customizer function that may take into account nested objects and properly copy them using lodash 4.x
var customizer = function(objValue, srcValue) {
if (typeof srcValue === 'object' && typeof srcValue !== null) {
return _.assignWith({}, srcValue, customizer);
}
return _.isUndefined(objValue) ? srcValue : objValue;
}
// This calls assign, but will invoke the customizer function
var result = _.assignWith({}, a, b, customizer);
result.bar.baz = 3;
result.foo = 4;
console.log(result, a, b);
// 'Constant' Array Example
const hi = [true, false, 'hi'];
hi[2] = 23;
console.log('hi.pop', hi.pop());
console.log('hi', hi);
// These will error, uncomment out to see it errors on any of these attempts
//hi = 3;
//hi = 'no';
hi = [true, false, 23];
//hi = false;
//hi = {};
The change doesn't reflect in b, because it wasn't a nested object during the assign operation so the property foo in our created object is pointing to a new primitive 1
var foo = {prop:1};
var bar = {prop:2};
var obj = {};
obj[foo] = 'value';
console.log(obj[bar]); //'value'
It is quite confusing why obj[bar] and obj[foo] are same now, whereas foo and bar are not same.
because
obj[foo]='value';
is the same as
obj["[object Object]"]='value';
Object keys are string so it's internally doing foo.toString()
and foo.toString() === bar.toString()
Every objects will return "[object Object]" if used as a key (not talking about arrays, numbers, strings..)
You'll need something that uniquely identify your objects, like below
var foo = {id:"foo", prop:1};
var bar = {id:"bar", prop:2};
var obj = {};
obj[foo.id] = 'value';
console.log(obj[bar.id]); //undefined
I came across this code snippet on Mozilla Developer Network (MDN) and I am racking my brain in trying to figure out why the result would indeed be 'value'
var foo = {unique_prop: 1}, bar = {unique_prop: 2}, object = {};
object[foo] = 'value';
console.log(object[bar]);
I would be grateful if someone would be so kind as to enlighten me!
object[foo] = 'value';
You can only have strings as identifiers and hence when the above runs, JavaScript internally calls ToString method, which represents "[object Object]". That's how objects are represented.
Now when you do object[bar], bar.toString() is also "[object Object]", and since 'value' is stored with "[object Object]" as key, it gets returned.
If you have a quick look in your console, you will see this is because foo is being coerced into a string (since all keys in Javascript are strings**), which defaults to [object object]. The string [object object] is the same for every object, so foo appears to be bar, but in essence it is not. Check out the below output:
var foo = {unique_prop: 1}, bar = {unique_prop: 2}, object = {};
object[foo] = 'value';
var output = document.getElementById('p')
for(thing in object){
output.textContent += thing + " = " + object[thing];
}
<p id='p'></p>
** I think that ES6 has a way of setting a computed key using {[func]: value} syntax, but I have not looked into this very deeply yet, so excuse me for the possible incorrectness.
You can see what's going on here with 3 mini experiments:
What is the result of toString() called on each of the objects you create?
foo.toString(), bar.toString() and object.toString() will output:
[object Object]
What is the result of object[{}]?
it is also "value", because the key that the runtime used to store your value is literally [object Object]
Let's change the behaviour of toString and see what happens.
Object.prototype.toString = function(){
return this.unique_prop;
};
// Re run the code
object[foo] = "value";
console.log(object[bar]); // Returns undefined
// Value was stored under the key "1"
console.log(object[1]); // Returns "value"
Because the key in this object is a string representation of the foo and bar objects, like
Object {[object Object]: "value"}.
As explained above, setting the object property results with an object stringifys the key
> console.log(foo.toString())
[Log] [object Object]
so object[foo] is equivalent to
object["[object Object]"] = 'value';
However if you actually wanted them to be different you could do something like this:
> console.log(JSON.stringify(foo))
[Log] {"unique_prop":1}
> object[JSON.stringify(foo)] = 'donkey'
> console.log(object)
[Log] {[object Object]: "value", {"unique_prop":1}: "donkey"}
> console.log(object[JSON.stringify(bar)])
[Log] undefined