Symbol

作者: 秋天de童话 | 来源:发表于2017-05-18 22:52 被阅读20次

1、概述
ES5对象属性名都是字符串容易造成属性名的冲突。

eg:var a = { name: 'lucy'};
a.name = 'lili';

这样就会重写属性

ES6引入了一种新的原始数据类型Symbol,表示独一无二的值。
七种数据类型
JavaScript 在 1997 年被标准化时,就有 6 种数据类型,直到 ES6 出现之前,程序中的变量一定是以下 6 种数据类型之一:
Undefined
Null
Boolean
Number (包括 NAN)
String
Object

注意,Symbol函数前不能使用new命令,否则会报错。这是因为生成的Symbol是一个原始类型的值,不是对象
Symbol函数可以接受一个字符串作为参数,表示对Symbol实例的描述,主要是为了在控制台显示,或者转为字符串时,比较容易区分。

var sym1 = Symbol();
var sym2 = Symbol("foo");
var sym3 = Symbol("foo");
console.log(sym1, sym2, sym3) //输出Symbol() Symbol(foo) Symbol(foo)

// 没有参数的情况
var s1 = Symbol();
var s2 = Symbol();
s1 === s2 // false

// 有参数的情况
var s1 = Symbol("foo");
var s2 = Symbol("foo");
s1 === s2 // false

Symbol值不能与其他类型的值进行运算
注:可以转为字符串,布尔值,不能转为数值

2、作为属性名的Symbol

var mySymbol = Symbol();

// 第一种写法
var a = {};
a[mySymbol] = 'Hello!';

// 第二种写法
var a = {
  [mySymbol]: 'Hello!'
};

// 第三种写法
var a = {};
Object.defineProperty(a, mySymbol, { value: 'Hello!' });

// 以上写法都得到同样结果
a[mySymbol] // "Hello!"

我们可以用typeof判断某一个变量类型为Symbol类型:

typeof Symbol() === 'symbol' //输出:true
typeof Symbol('foo') === 'symbol' //输出: true
typeof Symbol.iterator === 'symbol' //输出 : true

如果我们不知道Symbol的实例名字是什么,我们怎么获取到Symbol值的呢, Symbol无法被for in , for of循环,以及Object.keys, Object.values 等都无法遍历到Symbol的属性; Object下给我们提供了一个

getOwnPropertySymbols;

let sym0 = Symbol("o_o?");
let obj = {
    [sym0] : "heheda"
}
for( let prop of Object.getOwnPropertySymbols(obj) ) {
    //prop就是Symbol的名字
    console.log( obj[prop] ); //输出:heheda
};
或者用ES6提供的反射 : Reflect.ownKeys
let sym0 = Symbol("o_o?");
let obj = {
    [sym0] : "heheda"
}
console.log( Reflect.ownKeys(obj) ); //输出:[ Symbol(o_o?) ]

Symbol.for和Symbol的唯一区别是 Symbol.for创建的两个实例可能相等, 根据Symbol的参数生成实例, 如果参数一样, 那么会返回同一个实例;

let foo = Symbol.for( "1111" );
let bar = Symbol.for("1111");
console.log( foo === bar );  //输出: true
//只有通过Symbol.for创建的对象,才能用keyFor找到原来的参数;
console.log(Symbol.keyFor(foo)) //会输出:1111

当出现 key1 === key2 时就会有 Symbol.for( key1 ) === Symbol.for( key2 ) 。这种对应关系甚至是跨 service worker 和 iframe 的。

let privateProperty1 = Symbol.for( 'firstName' );
let privateProperty2 = Symbol.for( 'firstName' );
 
myObject[ privateProperty1 ] = 'Dave';
myObject[ privateProperty2 ] = 'Zsolt';
 
console.log( myObject[ privateProperty1 ] );
// Zsolt

因为 Symbol 注册表中的 Symbol 值和字符串之间有一一对应的关系,所以我们也可以检索字符串键。使用 Symbol.keyFor 方法。

Symbol.keyFor( privateProperty1 );
> "firstName"
 
Symbol.keyFor( Symbol() );
> undefined

Symbol 作为半私有属性键

即使 Symbol 不能使属性私有,它们也能用作带有私有属性的符号。你可以使用 Symbol 来分隔公有和私有属性的枚举 ,Symbol 能使它更清楚。

const _width = Symbol('width');
class Square {
    constructor( width0 ) {
        this[_width] = width0;
    }
    getWidth() {
        return this[_width];
    }
}

只要你能隐藏 _width 就行了,隐藏 _width 的方法之一是创建闭包:

let Square = (function() {
 
    const _width = Symbol('width');
 
    class Square {
        constructor( width0 ) {
            this[_width] = width0;
        }
        getWidth() {
            return this[_width];
        }
    }
 
    return Square;  
 
} )();

这样做的好处是,他人很难访问到我们对象的私有 _width 值,而且也能很好地区分,哪些属性是公有的,哪些属性是私有的。但这种方法的缺点也很明显:

通过调用 Object.getOwnPropertySymbols ,我们可以使用 Symbol 键。
如果要写很多的代码,这会使得开发者的体验不佳,访问私有属性不像 Java 或 TypeScript 那样方便。
如果你要用 Symbol 来表示私有字段,那你需要表明哪些属性不能被公开访问,如若有人试图违背这一规则,理应承担相应的后果。

内置的Symbol值
有11个方法,具体可以查看http://es6.ruanyifeng.com/#docs/symbol

相关文章

  • Symbol

    Symbol 每个Symbol都是独一无二的Symbol() !== Symbol() Symbol 不能进行运算...

  • Symbol

    1、window.Symbol 2、不允许new Symbol 3、symbol() !== symbol() 4...

  • Symbol学习笔记

    一.Symbol是什么 typeof Symbol() === 'symbol',symbol是js中第7种基本类...

  • ES6补充以及Node事件轮询

    Symbol es6中新增了symbol类型,symbol类型的值是通过symbol函数生成的,相同symbol函...

  • 深入理解ES6六

    Symbol ES6新增的数据类型Symbol 创建Symbol:通过去全局的Symbol函数创建一个Symbol...

  • JS-学习ES6之-Symbol数据类型[整理稿]

    为什么要有Symbol Symbol可以传参数 Symbol 作为属性名的用法 Symbol.for() 1. 为...

  • Symbol简单理解

    Symbol 概述 作为属性名的symbol 属性名的遍历 Symbol的方法 内置的symbol值 概述 Sym...

  • ES6-新增数据类型

    symbol类型 全局函数window.Symbol() typeof window.Symbol() 返回的类型...

  • ES6-Symbol

    创建Symbol实例let s1 = Symbol()let s2 = Symbol('another symbo...

  • umdh--查找内存泄漏--使用方法

    set _NT_SYMBOL_PATH=symbol目录多个目录,以’;’隔开 例:Set _NT_SYMBOL_...

网友评论

      本文标题:Symbol

      本文链接:https://www.haomeiwen.com/subject/ifjexxtx.html