es6新数据类型-Symbol

Date:2017/07/6       Cat:开发者手册       Word:共2700字       Tags:      

文章目录 「隐藏」
  1. Symbol原始类型
  2. Symbol类型作为属性名的遍历
    1. Reflect.ownKeys
  3. 可重复使用Symbol值
    1. Symbol.for
    2. Symbol.keyFor

参考:《ES6标准入门教程》 作者:阮一峰

Symbol原始类型

Javascript一共有6种原始数据类型,分别为:

  1. undefined
  2. null
  3. Boolean
  4. Object
  5. String
  6. Array

ES6新增加了一种原始数据类型,也就是说从ES6开始,Javascript一共有7种原始数据类型,全新的数据类型是Symbol类型,Symbol用来声明一个独一无二的值。因为Symbol类型返回的是一个原始类型值,不是返回的对象,也不能添加属性,所以在Symbol函数前不能使用new命令。

Symbol的参数是一个字符串,用于描述Symbol实例,如果为空则返回一个"Symbol()",并且每一个Symbol类型的值都是唯一的并且不相等的,比如:

var a = Symbol('1');
var b = Symbol('1');

a === b; // false

当我们使用typeof运算符来判断是什么类型的时候,返回的结果是如下:

var s = Symbol('this is s');

typeof s; // symbol

那Symbol到底有什么作用?很多时候我们要保证值的唯一性,防止被串改或者覆盖,比如我们使用switch判断的时候,通常我们会这样来建立一个对象来消除魔术字符串然后用对象的属性值来作判断,比如:

var persons = {
    a: '123'
}

function ifPerson(person) {
    switch(person) {
        case persons.a:
            console.log('a');
            break;
    }
}

ifPerson(persons.a); // a

同样也可以通过传递字符串来达到判断的效果,或者我们重新定义一个值等于123的变量来达到判断的效果:

var persons = {
    a: '123'
}

function ifPerson(person) {
    switch(person) {
        case persons.a:
            console.log('a');
            break;
    }
}

ifPerson(persons.a); // a
ifPerson('123'); // a

var b = '123';
ifPerson(b); // a

上面的方式都可以达到我们想要使判断输出a的效果,那问题来了,我们想要控制这个传递进来的值必须是我们指定的唯一值,并且不能用字符串或者值相等的属性、变量,来保证数据的唯一性,那这时候我们就可以使用到Symbol数据类型了。把上面的代码修改:

var persons = {
    a: Symbol('this is a')
}

function ifPerson(person) {
    switch(person) {
        case persons.a:
            console.log('a');
            break;
    }
}

ifPerson(persons.a); // a
ifPerson('123'); // undefined

var b = '123';
ifPerson(b); // undefined

通过上面的代码我们可以控制值的唯一性,防止覆盖串改;

同样我们可以把Symbol类型作为属性名,这样可以用来防止当别人拿到我们的对象时候新增或者修改、覆盖到对象重要的属性。如果使用Symbol类型当作属性名或者作为方法名调用的时候,必须把Symbol类型的值放在方括号中,比如下面的例子:

var printHello = Symbol('this is print "hello" function name');

var obj = {
    [printHello]() {
        console.log('hello');
    }
}

obj.printHello(); // undefined
obj[printHello](); // hello

Symbol类型作为属性名的遍历

Symbol作为属性名的时候,不会出现在for...infor...of循环中,同样也不会被Object.keysOjbect.getOwnPropertyNames()返回。但是他不是一个私有属性,有两个方法可以返回对象中含有Symbol类型的属性,分别是Object.getOwnPropertySymbols()Reflect.ownKeys()

Object.getOwnPropertySymbols

Object.getOwnPropertySymbols返回一个数组,返回当前对象所有用Symbol类型值当作属性名的属性。

var a = Symbol('a');
var b = Symbol('b');

var obj = {
    [a]: 'a',
    [b]: 'b',
    c : 'c'
}

Object.getOwnPropertySymbols(obj); // [Symbol(a), Symbol(b)]

Reflect.ownKeys

Reflect.ownKeys返回一个数组,返回当前对象所有的的属性,包括Symbol类型、可枚举和不可枚举的属性。

var a = Symbol('a');
var b = Symbol('b');

var obj = {
    [a]: 'a',
    [b]: 'b',
    c : 'c'
}

Reflect.ownKeys(obj); // ["c", Symbol(a), Symbol(b)]

可重复使用Symbol值

ES6为可重复使用的Symbol值定义了两个方法Symbol.forSymbol.keyFor

Symbol.for

Symbol.for方法同样有一个参数,这个参数是当前实例的Symbol类型数据的描述,Symbol.for()方法同样放回一个Symbol类型值,但是返回之前会先查找全局中是否存在同样的Symbol值,如果存在则返回这个存在的Symbol值,如果不存在则新创建一个Symbol值并返回。它和Symbol()不同的区别在于Symbol.for()返回的是一个登记的全局Symbol数据类型,而Symbol返回的一个唯一的Symbol类型值。

var a = Symbol.for('123');  // 第一次没有查找到全局中有登记为'123'的Symbol值
var b = Symbol.for('123');  // 第二次查找到全局中有登记为'123'的Symbol值,所以返回的值和变量a一样

a === b; // true

var a = Symbol('123');
var b = Symbol('123');

a === b; // false 两次返回的Symbol值都为唯一值,所以不相等

Symbol.keyFor

Symbol.keyFor返回Symbol类型登记的值,只返回登记的Symbol类型值,Symbol()生成的值不能使用。

var k = Symbol.for('this is k');
Symbol.keyFor(k); // 'this is k'

文完

《es6新数据类型-Symbol》留言数:0

发表留言