zoukankan      html  css  js  c++  java
  • ES6的原始类型数据——Symbol

    javascript中原始值,即基本数据类型,像Number,String,Boolean,undefined,Null都是基本类型值,保存在栈中,但是有个疑问:

    Symbol打印出来明明是个函数,具有prototype的属性,不能实例化的原因是:Symbol是个原始值。但Symbol明明就是个函数的鸭,而且: 

    Symbol.__proto__ === Function.prototype     //true
    Symbol.constructor === Function.prototype.constructor  //true
    Object.prototype.toString.call(Symbol)      //"[object Function]"
    typeof Symbol      //"function"
    typeof Symbol()   //"symbol"

     Symbol的原型指向的就是Function的原型,Symbol明明就是Function的实例鸭。

    其实JS中检测原始值的方法就是用typeof,那么typeof Symbol返回的就是function类型。typeof Symbol(),好嘛!!!返回symbol类型。

    在Javascript中函数即对象,是引用类型,为啥Symbol就是原始值,即基本类型呢?

    好吧!阮一峰这里有解释说:

    Symbol 值是原始类型,Symbol() 构造函数是对象。

    Question:我们知道Number,Array,String,Boolean,Object都是可以进行实例化对象操作的,就是使用new操作符,思考下,number,string,boolean也是基本类型,为何就可以使用new,而Symbol()就不行呢?

    解释下:symbol类型只能通过Symbol()函数的调用创建。symbol是基本类型,而Symbol()构造函数是个对象,既然是个构造器,为何就不能通过new操作符来实现一个实例化对象呢?

    这里提及下Javascript的包装对象,有三种就是Boolean,Number,String。显示的创建包装对象是可以的,利用new Boolean()等方法,但是Symbol()函数对象内部阻止你显示创建一个symbol包装对象,所以你不能用new来创建一个symbol对象。只能通过Symbol("s")来创建一个基本数据类型——symbol类型。

    如果你想创建一个Symbol包装对象,那么你可以先创建一个symbol基本类型值,然后通过Object()方法得到Symbol对象。"

     敲黑板:

    1,看栗子:

    var s1 = 'abc'
    var s2 = 'abc'
    console.log(s1 === s2)     //true
    var sym1 = Symbol('abc')
    var sym2 = Symbol('abc')
    console.log(sym1 === sym2)  //false
      console.log(Symbol.for('foo') === Symbol.for('foo'));//true

    但是Symbol.for(key)方法返回一个全局的Symbol变量,不会每次都创建新的symbol,而是返回之前已经创建的symbol。这不就是单例模式嘛!

     Symbol.keyFor(sym)方法返回定义symbol类型时传入的key字符串,如果没传入则为undefined。

    Object.getOwnPropertySymbols(obj):返回一个数组,数组成员是对象的所有属性名为Symbol值。

    const object1 = {};
    const a = Symbol('a');
    const b = Symbol.for('b');
    
    object1[a] = 'localSymbol';
    object1[b] = 'globalSymbol';
    
    const objectSymbols = Object.getOwnPropertySymbols(object1);
    console.log(objectSymbols)
    // [Symbol(a), Symbol(b)]
    Reflect.ownKeys(obj)
    // [Symbol(a), Symbol(b)]

    看阮一峰的文字呢,其实都是他自己的理解,每个人在对知识的理解上面会有些偏差,最好还是看官网吧。上面一段话意思是:Symbol()函数呢,返回一个类型为symbol的值,具有内置对象的静态属性和全局symbol的一些静态方法,类似于一个内置对象类,但是不能当做构造器函数,因为不支持“new Symbol()”语法。

    每个symbol都是Symbol()函数返回的,唯一的,可以作为对象的属性名,这是symbol类型存在的唯一目的,其他用处可以去更多了解Symbol。symbol类型是原始值。

    let sym = Symbol();
    
    let obj = {
        [sym]:"miya"
    }
    let a = {};
    Object.defineProperty(a,sym,{value:'miya'})
    
    console.log(obj[sym])  //miya
    console.log(a[sym])   //miya

    symbol值作为对象属性名只能通过[sym]来获取,不能通过点运算符。

    对象的symbol类型属性名,只能通过Object.getOwnPropertySymbols(obj)获取,通过for...in/of或者其他都是不行的。

    let s = Symbol();
    let obj = {
        [s](args){
            console.log(args)
        }
    }
    obj[s]('123')  //123

    上面的例子是:给对象obj里面添加s的属性方法,使用ES6支持的函数的写法,函数名可以使用symbol原始值类型。

    阮一峰举了一个使用symbol类型来消除魔术字的例子:

    const shapeType = {
        triangle:Symbol()
    }
    function getArea(shape,options){
        let area = 0;
        switch(shape){
            case shapeType.triangle:
            area = .5*options.width*options.height;
            break;
        }
        return area;
    }
    getArea(shapeType.triangle,{100,height:100})  //5000

    本来shapeType.triangle是个比较长的字符串,其实字符串是什么并不重要,只要属性值不冲突就行,刚好适合symbol的适用场景。

    【完】

    这两天都在了解Symbol类型,从最开始的云里雾里,扒了JS的包装对象,涨了些姿势。

  • 相关阅读:
    lua编程之协程介绍
    lua编程之元表与元方法
    设计模式系列之单例模式
    设计模式系列之生成器模式
    设计模式系列之抽象工厂模式
    设计模式系列之原型模式
    设计模式系列之工厂模式
    stl源码分析之hash table
    2018/2019款 MacBookPro 接口失灵的原因及解决方案
    test
  • 原文地址:https://www.cnblogs.com/tangjiao/p/10039659.html
Copyright © 2011-2022 走看看