Symbol类型详解

Symbol类型详解

  1. symbol类型通过Symbol函数生成,用于表示独一无二的值(不使用new关键字,直接调用即可创建。例:const s = Symbol("str")

  2. 即使使用相同的字符串来创建Symbol类型的值,这些值也是不同的

  3. symbol值可以调用 toString方法,也可以通过Boolean()转为 布尔值

    a.symbol本身转为布尔值时为true,取反为false
    b.toString调用后会返回Symbol(str)

  4. 在ES6中,支持用表达式 (变量)作为属性名,但表达式必须放在方括号里,由于每个Symbol值都是独一无二的,就可以用Symbol值作为属性名,且不会和其他属性名重复

  5. 使用symbol值作为属性名的属性访问只能使用name和 这个symbol值,例:obj[name]

  6. 属性名遍历

    a. symbol类型的属性并不是私有属性,但不能通过for in遍历到,也不能被Object.keys() Object。getOwnProperNames()Json.stringify()获取到
    b. symbol类型属性名可以通过Object.getOwnPropertySymbol()获取,但只能获取到symbol类型的属性名
    c. 使用ES6新提供的Reflect对象的 静态方法Reflect.ownKeys()可以获取全部属性名 ,包括symbol类型和非symbol类型

  7. symbol的静态方法

    a. Symbol.for()

    使用Symbol.fro()方法传入字符串,会先检查有没有使用这个字符串调用Symbol.for创建的symbol值,如果有,就返回该值,没有则进行创建

    通过Symbol.for创建的symbol值是全局范围内

    b. Symbol.keyFor()

    调用Symbol.keyfor传入一个symbol值可以返回该值在全局注册的键名,例

    const sym = Symbol.for("aaa");
    console.log(Symbol.keyFor(sym));
    //会返回aaa
    
  8. ES6的11个内置Symbol值

    a. Symbol.hasInstance

    对象的Symbol.hasInstance指向一个内部方法,如果给一个对象设置了以Symbol.hasInstance为属性名的方法,当其他对象使用instanceof来判断是否为该对象实例时,会调用这个方法,传入的参数为被判断的这个对象

    const obj = {
        [Symbol.hasInstance](obj2){
            console.log('obj2');
            //调用后会打印出{a:111}这个对象
        }
    };
    
    console.log({a:111} istanceof obj);
    //{a:111}会作为obj2传入Symbol.hasInstance
    

    b. Symbol.isConcatSpreadable

    该属性是一个可读写的布尔值,默认值为undefined,该属性控制数组是否能被扁平化,当值为false时,数组不能被扁平化,为true或undefined则可以,例:

    let arr1 = [1,2];
    console.log([].concat(arr1,[3,4]));
    //打印结果为[1,2,3,4]
    console.log(arr1[Symbol.isConcatSpreadable]);
    //此时该属性值为默认的undefined
    
    arr1[Symbol.isConcatSpreadable] = true;
    //把属性值设置为true
    console.log([].concat(arr1,[3,4]));//结果同上
    console.log(arr1[Symbol.isConcatSpreadable]);
    //属性值为true
    
    arr1[Symbol.isConcatSpreadable] = false;
    //再设置为false
    console.log([].concat(arr1,[3,4]));
    //此时的结果变成了[Array(2), 3, 4]
    //展开后是[[1, 2, Symbol(Symbol.isConcatSpreadable): false],3,4]
    //这里的Symbol(Symbol.isConcatSpreadable): false]不是一个元素,而是一个属性
    console.log(arr1[Symbol.isConcatSpreadable]);
    //false
    
    

    c. Symbol.species

    定义一个类C,使其继承自Array,再给类C创建一个实例对象c,c就能继承Array原型对象上的方法,通过c的map方法衍生一个a对象,分别打印a instanceof Ca instanceof Array,发现结果都为true,说明a既是C的实例对象,也是Array的实例对象

    class C extends Array{
        getName(){
            return 'aaa';
        }
    };
    const c = new C(1,2,3);
    const a = c.map(item=>item+1)
    console.log(a instanceof Array)
    console.log(a instanceof C)//两个结果都为true
    console.log(a.getName())//aaa
    

    如果需要让a只是Array的实例而不是C的实例,就需要使用Symbol.species,给C定义一个名为Symbol.specied的静态get存取器方法,并在该方法中返回要构造衍生数组的构造函数

    class C extends Array{
        static get[Symbol.species](){
            retrun Array;
        }
        getName(){
            return 'aaa';
        }
    };
    const c = new C(1,2,3);
    const a = c.map(item=>item+1)
    console.log(a instanceof Array)//打印true
    console.log(a instanceof C)//结果为false
    console.log(a.getName())//a不是C的实例,也不能调用getName方法,会报错a.getName is not a function
    

    d. Symbol.match,Symbol.replace,Symbol.search,Symbol.split

    这四个都指向一个内部方法,当在字符串上调用match,replace,search,和split方法时,会调用这个方法

    let obj = {
      [Symbol.match](str){
        return str.length
      }
    };
    
    console.log('aaaaa'.match(obj));//返回值为5
    

    e. Symbol.iterator

    数组的Symbol.iterator方法指向该数组的默认遍历器方法,该属性是可写的,可以自定义遍历器方法

    f. Symbol.toPrimitive

    Symbol.toPrimitive指向一个内部方法,当对象被转为原始类型是会调用这个方法,这个方法的参数是该对象被转为的类型

    const obj = {
      [Symbol.toPrimitive](type){
        console.log(type);
      }
    };
    
    const a = obj++
    //调用方法后会打印number
    

    g. Symbol.toStringTag

    对象的Symbol.toStringTag属性可以是一个字符串也可以是一个存取器get方法,当对象调用toString方法时,会返回[object 返回值]

    let obj = {
        //属性值为存取器get方法
      get [Symbol.toStringTag](){
        return 'aaa';
      }
    };
    
    let obj2 = {
        //字符串属性值
      [Symbol.toStringTag]:'bbb'
    }
    
    console.log(obj.toString());
    //打印[object aaa]
    console.log(obj2.toString());
    //打印[object bbb]
    

    h. Symbol.unscopables

    对象的该属性指向一个对象,可以控制这个对象的属性是否被with环境过滤,

    const obj={
      a:111,
      b:222,
      c:333,
    }
    
    obj[Symbol.unscopables]={
      a:true,
      b:false
    }
    
    with(obj){
      // console.log(a);
        //因为对a设置为了true,所以a属性会被with环境过滤掉,不能通过with访问,会报错
      console.log(b);//222
      console.log(c);//333
    }
    
    console.log(obj[Symbol.unscopables]);
    //{a: true, b: false}
    
    
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值