What does the es6 { [a]: b } destructuring mean? - javascript

There is some destructuring going on here:
const { [a]: b } = this.props
But, what does [a]: b do: what does the brackets with colon do?
In my case, a is supplied as one of the props with a string value.

This ES6 destructuring syntax is very similar to the new "Enhanced object literals" for defining objects with variable property names, so I think it's useful to see that first:
Pre-ES6, if you wanted to assign a value to an object with a property name that was variable, you would need to write
var obj = {};
obj[variable] = value
That's because while both the dot-notation and the object literal notation require using the actual property name, the obj[prop] notation allowed you to have a variable name.
ES6 introduced the extended object literal syntax, which included the ability to write
var obj = { [variable]: value }
The same syntax was incorporated in destructuring, which is what your question shows.
The basic destructuring allows assigning variables given literal property names:
First, assigning to a variable with the same name as a property already in the object (docs):
var person = {name: "Mary"};
var {name} = person;
/// name = "Mary"
Second, assigning a variable with a different name than the one already in the object (docs):
var person = {name: "Mary"};
var {name: myName} = person;
/// myName = "Mary"
(Side-note: if you recognize that, in the first example, var {name} = ... was just short-hand for var {name: name} = ..., you'll see that these two examples match more logically.)
But what if you don't know which property you want from person? Then you can use that same new computed-property-name object syntax from above (docs):
var person = {name: "Mary"};
var propName = getPropUserWantToKnowAbout(); // they type in "name"
var {[propName]: value} = person;
/// value = "Mary"

[a] is a computed property name
...allows you to put an expression in brackets [], that will be
computed and used as the property name
{ [a]: b } is a destructuring assignment with assigning to new variable names using a computed property name
A property can be unpacked from an object and assigned to a variable
with a different name than the object property
Thus you end up with having a variable b in current scope that holds the value of this.props[a]
Example
this.props = {foo : 1, bar: 2};
let p1 = 'foo';
let p2 = 'bar';
let { [p1]: b } = this.props;
console.log(b); // 1
let { [p2]: c } = this.props;
console.log(c); // 2

An example
var props = {'dynamic': 2}
var dyn = 'dynamic'
const {[dyn]:a} = props
console.log(a);
// logs 2
Check out this page: https://gist.github.com/mikaelbr/9900818
In short, if dyn is a string, and props has a property with that string as the name, accessible by props[dyn], then {[dyn]:a} = props will assign props[dyn] to a

Related

how to recognize when to use : or = in JavaScript?

How can I recognize when to use : or = in my code? I came from Java which does not have many : in it, so it's a new thing for me.
= is used to assign a value to a variable:
myVariable = 'someValue';
: is used when defining a property of an object:
myVariable = {
key: 'value in an object'
};
When we want to define property of an object then we always use :
Syntax
var object = {
property1 : value1,
property2 : value2,
property2 : value3
}
We always separate properties with comma in a single object
= Equal to always use as a assignment operator which assigns values to variables or constants
Syntax
var variable=value
value can be any type You can see this document for that
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Data_structures
Usually you use the : in objects for example:
object { car: 'BMW' }
And the = you use to define or update variables, example:
const car = 'BMW'; car = 'Mercedes-Benz'
: vs =
: is used in object, That is while assigning value's to key ex:-
const newObject = { key:value }
but when you assign some value to variable = sign is used

AngularJS $scope variable into one bind to display in html [duplicate]

This question already has answers here:
Add a property to a JavaScript object using a variable as the name? [duplicate]
(14 answers)
Closed 7 years ago.
I want to add a new property to 'myObj', name it 'string1' and give it a value of 'string2', but when I do it it returns 'undefined:
var myObj = new Object;
var a = 'string1';
var b = 'string2';
myObj.a = b;
alert(myObj.string1); //Returns 'undefined'
alert(myObj.a); //Returns 'string2'
In other words: How do I create an object property and give it the name stored in the variable, but not the name of the variable itself?
There's the dot notation and the bracket notation
myObj[a] = b;
ES6 introduces computed property names, which allow you to do
var myObj = {[a]: b};
Dot notation and the properties are equivalent. So you would accomplish like so:
// const myObj = new Object();
const myObj = {};
const a = 'string1';
myObj[a] = 'whatever';
alert(myObj.string1);
(alerts "whatever")
Ecu, if you do myObj.a, then it looks for the property named a of myObj.
If you do myObj[a] =b then it looks for the a.valueOf() property of myObj.
Oneliner:
obj = (function(attr, val){ var a = {}; a[attr]=val; return a; })('hash', 5);
Or:
attr = 'hash';
val = 5;
var obj = (obj={}, obj[attr]=val, obj);
Anything shorter?
You could just use this:
function createObject(propName, propValue){
this[propName] = propValue;
}
var myObj1 = new createObject('string1','string2');
Anything you pass as the first parameter will be the property name, and the second parameter is the property value.
You cannot use a variable to access a property via dot notation, instead use the array notation.
var obj= {
'name' : 'jroi'
};
var a = 'name';
alert(obj.a); //will not work
alert(obj[a]); //should work and alert jroi'
As $scope is an object, you can try with JavaScript by:
$scope['something'] = 'hey'
It is equal to:
$scope.something = 'hey'
I created a fiddle to test.
The following demonstrates an alternative approach for returning a key pair object using the form of (a, b). The first example uses the string 'key' as the property name, and 'val' as the value.
Example #1:
(function(o,a,b){return o[a]=b,o})({},'key','val');
Example: #2:
var obj = { foo: 'bar' };
(function(o,a,b){return o[a]=b,o})(obj,'key','val');
As shown in the second example, this can modify existing objects, too (if property is already defined in the object, value will be overwritten).
Result #1: { key: 'val' }
Result #2: { foo: 'bar', key: 'val' }

Object.freeze() vs const

Object.freeze() seems like a transitional convenience method to move towards using const in ES6.
Are there cases where both take their place in the code or is there a preferred way to work with immutable data?
Should I use Object.freeze() until the moment all browsers I work with support const then switch to using const instead?
const and Object.freeze are two completely different things.
const applies to bindings ("variables"). It creates an immutable binding, i.e. you cannot assign a new value to the binding.
Object.freeze works on values, and more specifically, object values. It makes an object immutable, i.e. you cannot change its properties.
In ES5 Object.freeze doesn't work on primitives, which would probably be more commonly declared using const than objects. You can freeze primitives in ES6, but then you also have support for const.
On the other hand const used to declare objects doesn't "freeze" them, you just can't redeclare the whole object, but you can modify its keys freely. On the other hand you can redeclare frozen objects.
Object.freeze is also shallow, so you'd need to recursively apply it on nested objects to protect them.
var ob1 = {
foo : 1,
bar : {
value : 2
}
};
Object.freeze( ob1 );
const ob2 = {
foo : 1,
bar : {
value : 2
}
}
ob1.foo = 4; // (frozen) ob1.foo not modified
ob2.foo = 4; // (const) ob2.foo modified
ob1.bar.value = 4; // (frozen) modified, because ob1.bar is nested
ob2.bar.value = 4; // (const) modified
ob1.bar = 4; // (frozen) not modified, bar is a key of obj1
ob2.bar = 4; // (const) modified
ob1 = {}; // (frozen) ob1 redeclared
ob2 = {}; // (const) ob2 not redeclared
Summary:
const and Object.freeze() serve totally different purposes.
const is there for declaring a variable which has to assinged right away and can't be reassigned. variables declared by const are block scoped and not function scoped like variables declared with var
Object.freeze() is a method which accepts an object and returns the same object. Now the object cannot have any of its properties removed or any new properties added.
Examples const:
Example 1: Can't reassign const
const foo = 5;
foo = 6;
The following code throws an error because we are trying to reassign the variable foo who was declared with the const keyword, we can't reassign it.
Example 2: Data structures which are assigned to const can be mutated
const object = {
prop1: 1,
prop2: 2
}
object.prop1 = 5; // object is still mutable!
object.prop3 = 3; // object is still mutable!
console.log(object); // object is mutated
In this example we declare a variable using the const keyword and assign an object to it. Although we can't reassign to this variable called object, we can mutate the object itself. If we change existing properties or add new properties this will this have effect. To disable any changes to the object we need Object.freeze().
Examples Object.freeze():
Example 1: Can't mutate a frozen object
object1 = {
prop1: 1,
prop2: 2
}
object2 = Object.freeze(object1);
console.log(object1 === object2); // both objects are refer to the same instance
object2.prop3 = 3; // no new property can be added, won't work
delete object2.prop1; // no property can be deleted, won't work
console.log(object2); // object unchanged
In this example when we call Object.freeze() and give object1 as an argument the function returns the object which is now 'frozen'. If we compare the reference of the new object to the old object using the === operator we can observe that they refer to the same object. Also when we try to add or remove any properties we can see that this does not have any effect (will throw error in strict mode).
Example 2: Objects with references aren't fully frozen
const object = {
prop1: 1,
nestedObj: {
nestedProp1: 1,
nestedProp2: 2,
}
}
const frozen = Object.freeze(object);
frozen.prop1 = 5; // won't have any effect
frozen.nestedObj.nestedProp1 = 5; //will update because the nestedObject isn't frozen
console.log(frozen);
This example shows that the properties of nested objects (and other by reference data structures) are still mutable. So Object.freeze() doesn't fully 'freeze' the object when it has properties which are references (to e.g. Arrays, Objects).
Let be simple.
They are different. Check the comments on the code, that will explain each case.
Const - It is block scope variable like let, which value can not reassignment, re-declared .
That means
{
const val = 10; // you can not access it outside this block, block scope variable
}
console.log(val); // undefined because it is block scope
const constvalue = 1;
constvalue = 2; // will give error as we are re-assigning the value;
const obj = { a:1 , b:2};
obj.a = 3;
obj.c = 4;
console.log(obj); // obj = {a:3,b:2,c:4} we are not assigning the value of identifier we can
// change the object properties, const applied only on value, not with properties
obj = {x:1}; // error you are re-assigning the value of constant obj
obj.a = 2 ; // you can add, delete element of object
The whole understanding is that const is block scope and its value is not re-assigned.
Object.freeze:
The object root properties are unchangeable, also we can not add and delete more properties but we can reassign the whole object again.
var x = Object.freeze({data:1,
name:{
firstname:"hero", lastname:"nolast"
}
});
x.data = 12; // the object properties can not be change but in const you can do
x.firstname ="adasd"; // you can not add new properties to object but in const you can do
x.name.firstname = "dashdjkha"; // The nested value are changeable
//The thing you can do in Object.freeze but not in const
x = { a: 1}; // you can reassign the object when it is Object.freeze but const its not allowed
// One thing that is similar in both is, nested object are changeable
const obj1 = {nested :{a:10}};
var obj2 = Object.freeze({nested :{a:10}});
obj1.nested.a = 20; // both statement works
obj2.nested.a = 20;
Thanks.
var obj = {
a: 1,
b: 2
};
Object.freeze(obj);
obj.newField = 3; // You can't assign new field , or change current fields
The above example it completely makes your object immutable.
Lets look following example.
const obj = {
a: 1,
b: 2
};
obj.a = 13; // You can change a field
obj.newField = 3; // You can assign new field.
It won't give any error.
But If you try like that
const obj = {
a: 1,
b: 2
};
obj = {
t:4
};
It will throw an error like that "obj is read-only".
Another use case
const obj = {a:1};
var obj = 3;
It will throw Duplicate declaration "obj"
Also according to mozilla docs const explanation
The const declaration creates a read-only reference to a value. It
does not mean the value it holds is immutable, solely that the
variable identifier can not be reassigned.
This examples created according to babeljs ES6 features.

Difference between javascript object literal notation and adding to objects

Can someone explain what is happening in the code below? I'd expect toString to get called for either both foo and bar, or neither. How is literal object notation different from adding fields to an object after it is created?
function Obj(v) {
this.v = v;
};
Obj.prototype.toString= function() {
window.alert("to string called for " +
this.v);
return this.v.toString();
}
var foo = new Obj('foo');
var bar = new Obj('bar');
// toString is not called here.
var map = {foo : 'blah'};
// toString is called here.
map[bar] = "blah2";
Why do object literals not use toString() while adding to an existing object does use toString()?
http://jsfiddle.net/pByGJ/2/
The main reason that object literals don't evaluate the identifier to the left of the colon is so you're not force to quote all literal names (as you do in JSON).
Bracket notation forces you to quote property names, if you don't, it will be evaluated as a variable.
The reason toString() does get called in the second example is because bar has to be converted to a string to be used as a property name.
In your first example, you're just creating a literal object (that is the exactly the same as {"foo" : 'blah'}). So that is never using the variable foo
If you want to create an object using a variable name, you can't use literal object notation, you have to use [] which is what forces it to call toString()
Here's a function to create objects with variable names in one expression.
function obj(key, value /*, key, value, ... */) {
var obj = {};
for (var i = 0, ln = arguments.length ; i < ln; i+=2) {
obj[arguments[i]] = arguments[i+1];
}
return obj;
}
Clearer Example
The fact that your variable names and values are the same doesn't help understanding the problem. Let me suggest this code
var foo = new Obj('fooValue');
var bar = new Obj('barValue');
var map = {foo : 'blah'};
map[bar] = "blah2";
// You expect map to be {fooValue: 'blah', barValue: 'blah2'}
// But it's {foo: 'blah', barValue: 'blah2'}
To do what you need, use my obj function
// Almost as clear as literal notation ???
var map = obj(
foo, 'blah',
bar, 'blah2'
);
// map = {fooValue: 'blah', barValue: 'blah2'} Yay!!
keys in an object literal are taken as strings, not interpreted as variables. This:
var map = {foo : 'blah'};
is equivalent to this:
var map = {"foo" : 'blah'};
and this:
var map = {};
map["foo"] = "blah";
but is completely different than this:
var map = {};
map[foo] = "blah";

How to create an object property from a variable value in JavaScript? [duplicate]

This question already has answers here:
Add a property to a JavaScript object using a variable as the name? [duplicate]
(14 answers)
Closed 7 years ago.
I want to add a new property to 'myObj', name it 'string1' and give it a value of 'string2', but when I do it it returns 'undefined:
var myObj = new Object;
var a = 'string1';
var b = 'string2';
myObj.a = b;
alert(myObj.string1); //Returns 'undefined'
alert(myObj.a); //Returns 'string2'
In other words: How do I create an object property and give it the name stored in the variable, but not the name of the variable itself?
There's the dot notation and the bracket notation
myObj[a] = b;
ES6 introduces computed property names, which allow you to do
var myObj = {[a]: b};
Dot notation and the properties are equivalent. So you would accomplish like so:
// const myObj = new Object();
const myObj = {};
const a = 'string1';
myObj[a] = 'whatever';
alert(myObj.string1);
(alerts "whatever")
Ecu, if you do myObj.a, then it looks for the property named a of myObj.
If you do myObj[a] =b then it looks for the a.valueOf() property of myObj.
Oneliner:
obj = (function(attr, val){ var a = {}; a[attr]=val; return a; })('hash', 5);
Or:
attr = 'hash';
val = 5;
var obj = (obj={}, obj[attr]=val, obj);
Anything shorter?
You could just use this:
function createObject(propName, propValue){
this[propName] = propValue;
}
var myObj1 = new createObject('string1','string2');
Anything you pass as the first parameter will be the property name, and the second parameter is the property value.
You cannot use a variable to access a property via dot notation, instead use the array notation.
var obj= {
'name' : 'jroi'
};
var a = 'name';
alert(obj.a); //will not work
alert(obj[a]); //should work and alert jroi'
As $scope is an object, you can try with JavaScript by:
$scope['something'] = 'hey'
It is equal to:
$scope.something = 'hey'
I created a fiddle to test.
The following demonstrates an alternative approach for returning a key pair object using the form of (a, b). The first example uses the string 'key' as the property name, and 'val' as the value.
Example #1:
(function(o,a,b){return o[a]=b,o})({},'key','val');
Example: #2:
var obj = { foo: 'bar' };
(function(o,a,b){return o[a]=b,o})(obj,'key','val');
As shown in the second example, this can modify existing objects, too (if property is already defined in the object, value will be overwritten).
Result #1: { key: 'val' }
Result #2: { foo: 'bar', key: 'val' }

Categories