zoukankan      html  css  js  c++  java
  • ES6笔记(4)-- Symbol类型

      系列文章 -- ES6笔记系列

    Symbol是什么?中文意思是标志、记号,顾名思义,它可以用了做记号。

    是的,它是一种标记的方法,被ES6引入作为一种新的数据类型,表示独一无二的值。

    由此,JS的数据类型多了一位成员:

    Number、String、Boolean、undefined、Object、Symbol

     

    一、简单使用

    1. 声明

    类似字符串String的声明方式 var str = 'str'; Symbol的声明方式类似,它调用构造函数Symbol()

    var s = Symbol();
    typeof s // symbol

    2. 使用

    Symbol声明了是为了使用

    var s = Symbol();
    var s1 = Symbol();
    
    console.log(s, s1);
    console.log(s == s1); // false

    Chrome的输出中自动对Symbol类型的数据做了标识处理,由输出知道,虽然通过Symbol生成的两个标志不相同,但两个变量混淆了分不清。

    实际上,为了区别出不同的symbol,我们可以在参数中指定

    var s = Symbol('s');
    var s1 = Symbol('s1');
    
    console.log(s, s1);

    symbol除了简单的在控制台输出之外,还可以参与到其他代码逻辑运算中去,最常见的是在对象属性名称中(为确保属性名惟一而存在)

    var s = Symbol();
    var s1 = Symbol('s1');
    
    var obj = {
        [s]: function() {
            console.log(1);
        },
        [Symbol()]: () => {
            console.log(2);
        },
        [s1]: 3
    };
    
    obj[s]() // 1
    obj[s1] // 3

    注意到symbol要使用[]中括号包裹起来,调用的时候也一样(不能使用obj.s的方式,这样会被识别成字符串)

    3. 属性的遍历

    如上代码,如果我们想遍历对象的属性值,也许会这样操作

    for (var item in obj) {
        if (typeof obj[item] === 'function') {
            obj[item]();
        } else {
            console.log(obj[item]);
        }
    }
    
    Object.keys(obj).forEach(function(item) {
        if (typeof obj[item] === 'function') {
            obj[item]();
        } else {
            console.log(obj[item]);
        }
    });

    却发现什么也没输出

    因为要获取到Symbol这个属性名,ES6引入了新的方法,旧的for...in  Object.keys()、Object.getOwnPropertyNames()等不支持访问

    使用新的getOwnPropertySymbols方法

    var s = Symbol();
    var s1 = Symbol('s1');
    
    var obj = {
        [s]: function() {
            console.log(1);
        },
        [Symbol()]: () => {
            console.log(2);
        },
        [s1]: 3,
        a: 4
    };
    
    
    
    Object.getOwnPropertySymbols(obj).forEach(function(item) {
        if (typeof obj[item] === 'function') {
            obj[item]();
        } else {
            console.log(obj[item]);
        }
    });
    
    // 输出 1 2 3

    虽然识别了symbol类属性,但常规属性却被忽略了,所以ES6还引入了一个新的内置类Reflect,它的ownKeys方法可以识别出所有属性名

    var s = Symbol();
    var s1 = Symbol('s1');
    
    var obj = {
        [s]: function() {
            console.log(1);
        },
        [Symbol()]: () => {
            console.log(2);
        },
        [s1]: 3,
        a: 4
    };
    
    
    
    Reflect.ownKeys(obj).forEach(function(item) {
        if (typeof obj[item] === 'function') {
            obj[item]();
        } else {
            console.log(obj[item]);
        }
    });
    
    // 输出 4 1 2 3

    4. 类型转换

    数字转换成字符串我们可以简单的使用 + '' 实现,symbol呢

    var s = Symbol();
    var s1 = Symbol('s1');
    
    s + '' // Uncaught TypeError: Cannot convert a Symbol value to a string

    出错了,提示不能转换。

    实际上,我们只是不能直接转换值,还是可以用toString或String方法转换这个标志的

    var s = Symbol();
    var s1 = Symbol('s1');
    
    s.toString() // Symbol()
    String(s1) // Symbol(s1)

    类似的,也可以转换为bool值

    var s = Symbol();
    var s1 = Symbol('s1');
    
    !!s // true
    !s // false
    Boolean(s1) // true

    不过,symbol是不能转换成数值Number类型的

    5. Symbol.for()相同值的使用

    有时候我们需要使用同一个symbol值,而调用Symbol()的时候会自动创建不同的值

    var temp = [];
    
    var scores = [{
        name: 'jack',
        score: 10
    }, {
        name: 'pick',
        score: 20
    }, {
        name: 'pick',
        score: 30
    }];
    
    scores.forEach(function(item) {
        
        temp.push({
            name: Symbol(item.name),
            score: item.score
        });
    });
    
    temp[1].name == temp[2].name // false

    以上代码主要为了登记不同用户的分数,并确保唯一性使用了symbol,但最终用户名都为pick的项不想等,可能会导致后续的计算出错

    把Symbol换成Symbol.for,输出才为true

    两者类似,都可以生成一个Symbol类型的值,但后者是先判断全局中是否有该symbol值,有就返回该值,没有才创建,并将该值登记在全局中

    var s = Symbol.for('s');
    var s1 = Symbol.for('s');
    
    s == s1 // true
    s === s1 // true
    
    var s = Symbol('s');
    var s1 = Symbol('s');
    
    s == s1 // false
    s === s1 // false

    此外,我们可以用Symbol.keyFor()访问全局中的symbol相关项,没有则返回undefined

    var s = Symbol.for('s');
    var s1 = Symbol.for('s');
    
    Symbol.keyFor(s) // s
    Symbol.keyFor(s1) // s
    Symbol.keyFor(s2) // Uncaught ReferenceError: s2 is not defined
    
    
    var s3 = Symbol('s3');
    Symbol.keyFor(s3) // undefined

    6. Symbol的更多使用

    Symbol的更多使用方法,可参考 MDN - Symbol

  • 相关阅读:
    什么是 DLL?
    如何用vc创建和读取xml文件??
    VC中调用 Excel 的总结
    Excel.cpp和Excel.h
    SQL中也可以用格式字符串定制日期转字符串
    REVERT权限切换
    透明数据加密
    批量恢复数据库
    FILESTREAM
    eclipse Tomcat热启动maven install Jrebel
  • 原文地址:https://www.cnblogs.com/imwtr/p/5912318.html
Copyright © 2011-2022 走看看