看阮一峰的教程他说Symbol对于一个对象由多个模块构成的情况非常有用,能防止某一个键被不小心改写或覆盖
这个应该怎么理解?
我试着写了下,好像感受不以Synmbol这东西是唯一的!!
这个唯一要怎么理解?
var x = Symbol('show');
var y = Symbol('hello');
var a = {
[x] : function(){
console.log('xxx');
},
[y] : function(){
console.log('yyy');
},
x : function(){
console.log('ssssss')
}
}
a.x() //ssssss
a[x]();//xxx
a[y]();//yyy
以前属性名只能是数字或者字符串,很容易发生覆盖,
但是如果用Symbol,完全可以这样玩
var a = {
[Symbol()] : function(){
console.log('xxx');
},
[Symbol()] : function(){
console.log('yyy');
}
}
因为Sysbol() !== Symbol()
始终为true,所以两个Symbol()不可能相等,这就避免了覆盖
不是Symbol()返回唯一的东西。是Symbol返回的东西是唯一的。
而且你也知道,一个对象不能有相同的key,可是下面的对象是合法的。
{
[Symbol()]: 1,
[Symbol()]: 1, // Symbol() !== Symbol()
[Symbol('x')]: 1,
[Symbol('y')]: 1, // Symbol('x') !== Symbol('y')
[Symbol('x')]: 1, // Symbol('x') !== Symbol('x')
}
Symbol返回的东西是唯一的。
而且楼上的例子也很清楚Symbol() !== Symbol()
,每次Symbol()返回的都是不一样的。
下面说说这个唯一怎么理解,为什么要用这个Symbol。
部署接口
你是js语法标准的制定者。现在你要为Array对象添加一个方法one
,用来输出这个数组中第一个元素。
const array = [1, 2, 3];
console.log(array.one()); // => 1
但是现在网上有大量的js代码,很多都对Array进行了拓展。为了保证现有的代码和你定的新方法名称不产生冲突,你会怎么办呢?毕竟你选的任何一个方法名都有可能和大家重复。
于是Symbol登场了。Symbol()每次返回的东西是唯一的,不和其他类型相同,所以你可以尽情地添加方法了。
Symbol.one = Symbol();
Array.prototype[Symbol.one] = function() {
return this[0];
}
Array.prototype.one = function() {
return 'taken';
}
const array = [1, 2, 3];
console.log(array[Symbol.one]()); // => 1
console.log(array.one()); // => 1
私有
你现在有了一个模块
function getModule() {
return {
_data: 'world',
hello(){
console.log(this._data);
}
}
}
const mod = getModule();
mod.hello(); // => world
但是使用的人很容易篡改
const mod = getModule();
mod._data = 'bug'
mod.hello(); // => bug
当别人使用你的模块的时候并不想让他们碰_data
,因为你认为这个是私有的。
解决办法呢?万能的闭包。
function getModule(module) {
let _data = 'world';
return (function(){
return {
hello(){
console.log(_data)
}
}
})()
}
const mod = getModule();
mod._data = 'bug'
mod.hello(); // => world
解决了私有的问题,但是出现了另一个问题。
调试的时候,根本无法从模块的外面知道这个模块到底有什么私有的数据。比如别人调试到你的程序的时候。
>utils.inspect(mod, {showHidden: true});
'{ hello: { \[Function: hello\] \[length\]: 0, \[name\]: \'hello\' } }'
但是在Node里,util.inspect无法看到闭包。
当然,如果在Chrome的devtool下,console.log()这个对象的时候是可以看function scope的。
这个时候最适合Symbol了。
const data = Symbol('data');
function getModule() {
return {
[data]: 'world',
hello(){
console.log(this[data])
}
}
}
这样,你在返回的对象上不管怎么赋值,都不会出现覆盖。可以被其他人随便封装。
const m = getModule();
m.data = 'bug';
m.hello(); // => world
m[Symbol('data')] = 'bug';
m.hello(); // => world
而且还可以inspect
看内部的数据。