Symbol in Javascript - javascript

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;
}
}

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.

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.

Related

JavaScript Conceptual Issue with a code. Please give an explanation for the output i am getting

I am having difficulty in understanding the following code, i have put a comment where i do not understand the concept, what exactly is going on
var ob = {};
var ob2 = ['name'];
for(var op of ob2)
{
ob[op]='at'; // here i dont understand what is happening, why here is an array type brackets
}
console.log(ob);
OUTPUT IS
name:'at'
That is just the syntax for accessing or assigning properties of an object dynamically in javascript.
You can think of it as though you are doing: ob.name = 'at'.
There are two ways to access object properties in JavaScript
var person = {
name: 'Jane'
}
person.name
// or
person['name']
// both return jane
in your case, that iterates through members of the array called ob2
first and only element of that array is a string name and it's given to that object as a prop, which becomes like following
ob['name'] = 'at';
// or
ob.name = 'at';
When to use brackets([]) over dot(.)
If you don't know the prop name at runtime you need to go with brackets, if you do know it you can choose either dot notation or brackets
Basically, it's accessing a property of the object ob. In this case, is accessing and creating new properties.
The loop is getting each index value, and for each assign/create a new property using that index value.
That approach is a dynamically way of creating property-names in an object.
ob['name'] = 'at';
ob.name = 'at'; // Just to illustrate
Read a little the docs here -> JavaScript object basics - Learn web development | MDN

What is the use of Symbol in javascript ECMAScript 6? [duplicate]

This question already has answers here:
What is the motivation for bringing Symbols to ES6?
(7 answers)
What is the point of the 'Symbol' type in ECMA-262-v6?
(2 answers)
Closed 4 years ago.
What is the use of Symbol in javascript (ECMASCRIPT6)?
Why does the example below return false?
const symbol1 = Symbol();
console.log(Symbol('foo') === Symbol('foo'));
// expected output: false
Symbol is used to create a totally unique, one-of-a-kind identifier. It's use is precisely for the example you list.
Even if you call Symbol with the same string, the instances will be different. This allows different libraries (which may be used at the same time) to define keys which may be used at the same time.
For example, imagine two libraries using a common name to define something on window or global (or for illustration, the fake global door):
const door = {};
// from library 1
door.cake = () => console.log('chocolate');
// from library 2
door.cake = () => console.log('vanilla');
// your code
door.cake();
In this example, the first libraries code is lost because it was unintentionally given the same name as the first.
Now, if they both use Symbol, then even if they are named the same, you can still access both (assuming they export Symbol somehow):
const door = {};
// library 1
const cake1 = Symbol('cake');
door[cake1] = () => console.log('chocolate');
// library 2
const cake2 = Symbol('cake');
door[cake2] = () => console.log('vanilla');
// your code
door[cake1]();
door[cake2]();
Both are still accessible.
That is a bit of an oversimplification, but it illustrated the point.
In a more practical usage, these are used for things such as importing modules. The modules may end up with the same name, but that's okay because they'll have unique symbols associated with them, which makes them uniquely accessible as long as your have the Symbol objects.
As for when to use them yourself... it's probably going to be pretty rare. You'll mainly want to use them any time you have a way to provide the Symbol but need other things to remain unique. I've only used these directly in a few narrow circumstances where the created element may end up the same.
For example, if you were making an object using names as the key, you might have duplicate names. Without symbols, the objects would override one other. With symbols, they'll all remain.
const people = {};
people[Symbol('bob')] = { name: 'Bob Smith' };
people[Symbol('bob')] = { name: 'Bob Jones' };
From the documentation:
Every symbol value returned from Symbol() is unique.
That means === comparisons will fail because they're not identical.
If you want a unique identifier of some sort that can be given a descriptive, if otherwise irrelevant name, then Symbol might be useful.
The Idea of the symbol is to introduce private properties into Javascript. But, its actual purpose is for name collision.
Unfortunately, however, they ended up being severely downgraded, and not private after all, because you can find them via reflection. Specifically, via the Object.getOwnPropertySymbols method and through proxies.
Every symbol value returned from Symbol() is unique. A symbol value may be used as an identifier for object properties; this is the data type's only purpose. (as per mozilla)
var Pet = (function() {
var typeSymbol = Symbol('type');
function Pet(type) {
this[typeSymbol] = type;
}
Pet.prototype.getType = function(){
return this[typeSymbol];
}
return Pet;
}());
var a = new Pet('dog');
console.log(a.getType()); // prints dog
a[Object.getOwnPropertySymbols(a)[0]] = "cat"
console.log(a.getType()); //prints cat

What is the difference between Javascript Object, Property and Variable, are they all the same?

What is the difference between a JS:
Object, Property and Variable ?
Sorry I'm new to JavaScript but from the way I'm understanding it is a Variable is a container to store information/data types yes ?
An object is a variable but with several different properties (whereas with a variable you have one property)? name:value pairs
a property is the building blocks of objects? is that what makes an Object an Object? because it is a variable with several name:value pairs? ........
I'm supper confused!!! are all three the same are they like interchangeable?
the only example I can think of is
Human body:
Cells
Tissues
Organs
-organs are made up of tissues
-tissues are made up of cells
-cells are tissues, basically lots of cells make up tissues and lots of tissues make up organs.
So basically organs are also cells but they are made up of a lot of cells?
I'm a bit dumb and slow when it comes to learning can somebody please enlighten me?
Explain the differences between them in very simple basic language like your explaining it to a 10 year old or something please
answers much appreciated,
Thanks :)
ps There may be a part 2 to this question
the way I'm understanding it is a Variable is a container to store information/data types yes ?
Almost. A variable is a container that stores a value. Each value is of a specific data type. Common types are number, string and Boolean.
Example:
var userID = 42;
userID is a variable. It contains the value 42. 42 is a number value, i.e. it is of type number.
A JavaScript object is a value of type object. Objects are not just simple, scalar values, they are "container" values. They can themselves contain multiple different values.
Essentially objects are key-value stores, i.e. they contain one or more keys associated with a value. These key-value pairs are called properties.
Example:
var record = {
name: 'Paul',
age: 42
};
record is a variable. It contains an object as value. The object has two properties, name and age. name holds a string value, age a number value.
When one refers to 'variable' one typically imagine a container with some memory to hold a value.
Objects are variables too but dynamically transform to containers of primitives or more-complex values upon Assignment! Complex values can be objects that hold primitive data types or even other objects such in the example below :
var SNOCounter; //gives undefined ^
SNOCounter = 3;
AccObjVar = {firstName:"John", lastName:"Smith"}; //creates an JS "object" variable with two "properties" that hold 'string' type values
AccountWrapperObj = {SNO:SNOCounter,AccountName:AccObjVar};
The dynamism of object properties is such that although AccountWrapperObj which is a JS Object holds a primitive value and Object as its original value. Replacing the AccountName property with an integer can be done by just assigning it the integer value (the properties have dynamic data types just like variables in Javascript)
AccountWrapperObj.AccountName= 'Albert Einstein'; // changes the type of AccountName from AccObjVar object type to a String
----------Extra Info ---------------
^ I am not quite clear on the memory assignment part at this stage. Link says there needs to be a bare minimum memory here for referencing the variable and actually assigning it a value.
Does declaring a variable in JavaScript with var without assignment consume memory?
A variable is a binding to a value in memory and not an object.
The item in a box analogy isn’t quite right. I think that it’s more along the lines of two tin cans connected by a string, one can being the reference(variable) and the other being the value.
I'm also new to JS, so I'll tell what's helping me here
one thing that's helping me is to think about variables as 'labels', something temporary related to execution (a metaphor from Luciano Ramalho's Fluent Python book...), and not as 'boxes', a metaphor that I've seen in a lot of tutorials
so variables are temporary, and related to execution of some function, or of the whole script (depending of where they're declared... see the difference of var, let and const for more about this)
properties, on the other hand, are related to objects, attached to the obj while it or the property exists; so you cannot create a property that's not related to an obj
let myObj = {}; // 'myObj' is the 'label' of the obj we're creating
myObj.prop = true; // we create 'prop', a property of 'myObj', using the dot notation
almost everything in JS is an obj, and objs are custom types/structures for data; functions are also objects, but they're a 'special' kind of obj, we can create and return objects with them (we can execute functions to create/return objs); so
let foo; // declaring an empty variable; the word let is related to the scope of the variable, you can use var, let or const when declaring variables
foo = function(){ return {}; }; // foo returns an empty obj
myObj = foo(); // we execute foo() so that myObj is again an empty obj
the value of a property can also be an object, so we can also do
myObj.foo = function(...args){ // receives no or more arguments
const createProps = (el, i) => { // declares a variable and defines an arrow function
this[`prop${i+1}`] = el; // uses the index of the argument to create the name of the property, with the argument value
}
args.forEach(createProps); // for each arg, create a property
}
myObj.foo('some', 'new', 'properties'); // execute the function, creating new properties in 'myObj'
above, the function that creates properties for my myObj is part of myObj, as a property...
so objects and properties have to do with data structuring, how I relate the different kinds of data in my code; and functions and variables - these 'temporary labels' - have to do with execution, doin' stuff, creating objs, and so on... both 'portions' workin' together, of course

JavaScript NameSpace Global Variable vs Global Property

I have two part question about creating namespaces in JavaScript, which one of the following is proper/better way to define a namespace:
// style 1
var company = company || {};
company.models = company.models || {};
company.models.class = {...}
// style 2
company = typeof (company) == 'undefined' ? {} : company;
company.models = company.models || {};
company.models.class = {...}
Please note there are TWO differences in the styles. First is use of typeof and Second is the style 2 does NOT use the var key.
Both these styles seem to work and now here is where it gets really confusing. If I remove the var key from style 1 then namespace does NOT work at all. I get something like company is not defined. I think it has something to do with the var creating a global variable and without var we are creating a global property as explained in here
What is the purpose of the var keyword and when to use it (or omit it)?
Would some please explain to me why the style 1 fails without the var key?
Many thanks in advance.
It's matter of likes but I prefer the first one since It is shorter and more readable.
First style 'means':
Create local variable 'company'. If it exists(and its value is not falsy) in an upper scope asign that to this variable else asign a new object.
Second one 'means'
Assign to company variable a new object if it is undefined or itself if it is defined.
The first one triggers a ReferenceError if you remove 'var' because the second reference (company = company) doesn't exists and the interpreter doesn't know how to deal with that. If it exists it will work even if you remove 'var'.
Another note for the first style is that company will be overwritten with a new object even if it is a falsy value like 0, null or ""

What is the name of the technique the example uses to pass a variable to an object in javascript?

What is the name of the technique the example uses below to pass a variable to an object in javascript? And furthermore, why is it not working ("large" is not outputted to the console log as expected)?
var thumbnailBlock = new ThumbnailBlock();
thumbnailBlock.thumbnailSize = "large";
function ThumbnailBlock() {
this.thumbnailSize;
console.log("DEBUG");
console.log(this.thumbnailSize);
}
The explanation what is going wrong in your code from Willem Mulder's answer:
There is no specific name. You simply set an object property.
The 'large' is not outputted because you first create an object using the ThumbnailBlock constructur function (where it logs the this.thumbnailSize) and only then set the .thumbnailSize to "large".
You could pass the size as function argument.
function ThumbnailBlock(size) {
this.thumbnailSize = size;
}
var thumbnailBlock = new ThumbnailBlock("large");
console.log(thumbnailBlock.thumbnailSize);
Also, have a look at the The Constructor Pattern and other nice patterns on that page. I also recommend the chapter on OOP in the free book Eloquent JavaScript.
There is no specific name. You simply set an object property.
The 'large' is not outputted because you first create an object using the ThumbnailBlock constructur function (where it logs the this.thumbnailSize) and only then set the .thumbnailSize to "large".
The proper answers are already given, I just want to point out for the record that adding dynamic property won't work if your object is sealed or frozen.
function ThumbnailBlock(size) {
Object.seal(this);
}
var thumbnailBlock = new ThumbnailBlock("large");
thumbnailBlock.thumbnailSize = 10;
console.log(thumbnailBlock.thumbnailSize); // undefined
In strict mode you will raise an exception instead.

Categories

Resources