What is the motivation for bringing Symbols to ES6?
UPDATE : Recently a brilliant article from Mozilla came up. Read it if you're curious.
As you may know they are planning to include new Symbol primitive type in ECMAScript 6 (not to mention some other crazy stuff). I always thought that the :symbol
notion in Ruby is needless; we could easily use plain strings instead, like we do in JavaScript. And now they decide to complicate things in JS with that.
I don't understand the motivation. Could someone explain to me whether we really need symbols in JavaScript?
The original motivation for introducing symbols to Javascript was to enable private properties.
Unfortunately, they ended up being severely downgraded. They are no longer private, since you can find them via reflection, for example, using Object.getOwnPropertySymbols
or proxies.
They are now known as unique symbols and their only intended use is to avoid name clashes between properties. For example, ECMAScript itself can now introduce extension hooks via certain methods that you can put on objects (eg to define their iteration protocol) without risking them to clash with user names.
Whether that is strong enough a motivation to add symbols to the language is debatable.
Symbols do not guarantee true privacy but can be used to separate public and internal properties of objects. Let's take an example where we can use Symbol
for having private properties.
Let's take an example where a property of an object is not private.
var Pet = (function() {
function Pet(type) {
this.type = type;
}
Pet.prototype.getType = function() {
return this.type;
}
return Pet;
}());
var a = new Pet('dog');
console.log(a.getType());//Output: dog
a.type = null;
//Modified outside
console.log(a.getType());//Output: null
Above, the Pet
class property type
is not private. To make it private we have to create a closure. The below example illustrates how we can make type
private using a closure.
var Pet = (function() {
function Pet(type) {
this.getType = function(){
return type;
};
}
return Pet;
}());
var b = new Pet('dog');
console.log(b.getType());//dog
b.type = null;
//Stays private
console.log(b.getType());//dog
Disadvantage of above approach: We are introducing an extra closure for each Pet
instance created, which can harm performance.
Now we introduce Symbol
. This can help us make a property private without using extra unnecessary closures. Code example below:
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());//Output: dog
a.type = null;
//Stays private
console.log(a.getType());//Output: dog
Symbols
are a new, special kind of object that can be used as a unique property name in objects. Using Symbol
s instead of string
s allows different modules to create properties that don't conflict with one another. Symbols
can also be made private, so that their properties can't be accessed by anyone who doesn't already have direct access to the Symbol
.
Symbols
are a new primitive . Just like the number
, string
, and boolean
primitives, Symbol
s have a function which can be used to create them. Unlike the other primitives, Symbols
do not have a literal syntax (eg how string
s have ''
) - the only way to create them is with the Symbol
constructor in the following way:
let symbol = Symbol();
In reality, Symbol
s are just a slightly different way to attach properties to an object - you could easily provide the well-known Symbol
s as standard methods, just like Object.prototype.hasOwnProperty
which appears in everything that inherits from Object
.
Here are some of the benefits of the Symbol
primitive type.
Symbols
have debuggability built in
Symbols
can be given a description, which is really just used for debugging to make life a little easier when logging them to a console.
Symbols
can be used as Object
keys
This is where Symbol
s get really interesting. They are heavily intertwined with objects. Symbol
s can be assigned as keys to objects, meaning you can assign an unlimited number of unique Symbol
s to an object and be guaranteed that these will never conflict with string
keys, or other unique Symbol
s.
Symbols
can be used as a unique value.
Let's assume you have a logging library, which includes multiple log levels such as logger.levels.DEBUG
, logger.levels.INFO
, logger.levels.WARN
and so on. In ES5 code you'd like make these string
s (so logger.levels.DEBUG === 'debug'
), or number
s ( logger.levels.DEBUG === 10
). Both of these aren't ideal as those values aren't unique values, but Symbol
s are! So logger.levels
simply becomes:
log.levels = {
DEBUG: Symbol('debug'),
INFO: Symbol('info'),
WARN: Symbol('warn'),
};
log(log.levels.DEBUG, 'debug message');
log(log.levels.INFO, 'info message');
Read more in this great article.
链接地址: http://www.djcxy.com/p/51708.html上一篇: 带有complexContent,restriction和attribute的jaxb元素
下一篇: 把符号带到ES6的动机是什么?