Reputation: 307
I saw following code in a project. can anyone explain what is going on here? What will be value of Attributes? What is happening this[Attributes] = attrs
line?
const Attributes = Symbol('User#attrs');
class User {
constructor (attrs) {
this[Attributes] = attrs;
}
}
Upvotes: 0
Views: 106
Reputation: 707298
Edit
Since you've now clarified the question to be only about the line of code this[Attributes] = attrs
, see the second part of my answer for discussion of that.
Original Answer
This is a couple of the new ES6 Javascript features.
const Attributes = Symbol('User#attrs');
creates a new Symbol object. The Symbol function and object is described here. It creates a unique identifier object that can then be used for many other uses, one of which is as a property name. There are many other references on the new Symbol feature so I won't repeat all of that here.
The class
definition is the ES6 method for declaring prototyped classes. Again, there are many other references on this new syntax so there is no point in repeating all that here. There's an example below of what the equivalent ES5 code is.
This line this[Attributes] = attrs;
uses the Symbol generated above to set a property on the newly created object.
The class definition is equivalent to the regular constructor declaration like this:
function User(attrs) {
this[Attributes] = attrs;
}
Discussion of this[Attributes] = attrs
Attributes
is a symbol which can be used as a property name on an object. It's a way of generating a unique key that can be used as a property name. So, this[Attributes] = attrs
is setting a property on the newly constructed object and it is using the Attributes
symbol as the property name. This Attributes
symbol is a unique value that will not match any known string (in fact it won't even match other Symbol objects) so it's a way of making a unique property name.
It is unclear why the code does this:
this[Attributes] = attrs;
instead of just something like this:
this.attrs = attrs;
We would have to see a bit more context for how that is being used and why a plain string property could not also be used in place of the Symbol as you haven't provided enough context for us to know.
One possible use is for privacy. If Attributes
is not public, then this is a way of creating a property on the object that the outside world doesn't know how to access because you have to have the current value of Attributes
in order to access that properly. As you've shown the code with User
and Attributes
in the same scope that does not seem like it is private, but perhaps only User
is exported to a public scope.
Another possible use is for uniqueness. If the User
object may have lots of other properties added to it by other code, then Attributes
creates a unique property name that cannot collide with other property names. This seems less likely in this case, but it is one possible use of Symbols.
Upvotes: 2
Reputation: 159905
Symbol
creates an un-collidable key for any object:
const first = Symbol('debug-name');
const second = Symbol('debug-name');
first !== second // true;
const anObj = {};
anObj[first] = 123;
anObj[second] = 456;
console.log(anObj) // {Symbol('debug-name'): 123, Symbol('debug-name'): 456}
Note that even though the first
and second
variables have the same debugging string they create different keys in anObj
. Anyone who has access to first
can add that key to any object and it will not collide with any other key in that object.
This can be used instead of magic strings to manage protocols:
// ES5
someObject.MY_LIB_attributes = [1, 2, 3];
// Only safe if no other library uses the key
// "MY_LIB_attributes"
// ES2015+
export const Attributes = Symbol('myLib#attributes');
import { Attributes } from 'my-lib';
someObj[Attributes] = [1, 2, 3];
// Safe as long as no other library uses
// *this* Symbol instance for some other purpose.
Upvotes: 3