• Symbol类型


    Symbol 是ES6引入的一种新的原始数据类型,由于Symbol是一个原始类型的值,不是对象,不能添加属性.基本上
    是一种类似于字符串的数据类型

    概述

    Symbol 可以接受一个字符串作为参数,主要是为了容易区分
    Symbol 函数的参数只是对当前Symbol的描述,相同参数的Symbol返回值是不相同的
    Symbol 值不能与其他类型的值进行运算(字符串的加运算)
    Symbol 可以转字符串,布尔值
    var sys =Symbol() // Symbol()
    sys.toString() // "Symbol()"
    Boolean(sys) //true
    !sys //false
    

    作为属性名的Symbol

    由于每一个Symbol都是不相同的 意味Symbol值可以作为标识符用于对象的属性名,保证不会出现同名的属性
    var mySymbol = Symbol()
    1.
    var a ={}
    a[mySymbol]='hello'
    2.
    var a ={[mySymbol]:'hello'}
    3.
    var a = {}
    object.defineProperty(a,mySymbol,{value:'hello'})
    * Symbol值作为属性名的时候,不能使用点选运算符,因为点运算符后面总是字符串,所以实际的属性名是一个字符串
    而不是Symbol值.同理,Symbol值在对象里的时候必须放在[]符号内
    eg1:
    const COLOR_RED =Symbol()
    const COLOR_GREEN =Symbol()
    function tes1t(color){
    switch(color){
        case COLOR_RED:
        return COLOR_GREEN;
        case COLOR_RED:
        return COLOR_GREEN;
        default:
        throw new Error('undefined color')
     }
    }
    eg2:
    const obj={
    DEBUGGER:Symbol('debugger')
    }
    

    魔术字符串

    魔术字符串是指在代码中多次出现、与代码形成强耦合的某一个具体字符串或者数值

    var shapeType={triangle:'triangle'}
    function getArea(shape,options){
    	var area=0
    	switch(shape){
    	case shapeType.triangle:
    	area=1*options.height*options.width
    	break
    	}
    	return area
    }
    var shapeType={triangle:Symbol()}
    function getArea(shape,options){
    	var area=0
    	switch(shape){
    	case shapeType.triangle:
    	area=1*options.height*options.width
    	break
    	}
    	return area
    }
    getArea(shapeType.triangle,{10,height:20}) //200
    shapeType.triangle //Symbol()
    

    Symbol.for,Symbol.keyFor()

    Symbol.for

    1.Symbol()[未登记的Symbol值]和Symbol.for()都会生成新的Symbol,区别在于前者会被登记在全局环境中供搜索
    2.Symbol.for()不会每次调用都返回一个新的Symbol值,而是会在全局先检查给定的key是否已经
    存在,如果不存在就新建一个,如果存在会返回同一个Symbol值
    var s1 = Symbol('cat')
    var s2 = Symbol('cat')
    s1==s2  //false
    var s1 = Symbol.for('cat')
    var s2 = Symbol.for('cat')
    s1==s2  //true
    

    symbol.keyFor()

    Symbol.keyFor() 方法返回一个已经登记的Symbol类型的key值
    var s1 =Symbol.for('cat')
    Symbol.keyFor(s1)  //'cat'
    var s1 =Symbol('cat')
    Symbol.keyFor(s1) //undefined
    
    var test = Symbol()
    var test2=Symbol()
    test1==test //false
    // 使用Symbol.for(),可以重新使用一个Symbol值
    var test1 = Symbol.for()
    var test2 = Symbol.for()
    test1===test2 //true
    * Symbol.for 为Symbol值登记名字是全局环境的,可以在不同的iframe或service worker中获取
    iframe = document.creatElement('iframe')
    iframe.src = String(window.location)
    document.body.appendChild(iframe)
    iframe.contentWindow.Symbol.for('foo') ==Symbol.for('foo')  //true
    
    

    属性名的遍历

    Object.getOwnPropertyNames()只能返回Symbol类型的键名 Reflect.ownkeys可以返回所有类型的键名

    Symbol作为属性名的时候不会出现在for...in for...of循环中,也不会出现在Object.keys,Object.getOwnPropertyNames
    返回,会被Object.getOwnPropertySymbols获取指定对象的所有用作属性名的Symbol值
    var obj ={}
    var a = Symbol('a')
    var b = Symbol('b')
    var objProperty  = Object.getOwnPropertySymbols(obj)
    obj // {Symbol(a): "hello", Symbol(b): "world"}
    ObjProperty // [Symbol(a), Symbol(b)]
    let obj ={}
    let obj ={[Symbol('key')]:1,enum:2,nonEnum:3}
    Reflect.ownKeys(obj) //["enum", "nonEnum", Symbol(key)]
    
    以Symbol值作为名称的属性不会被常规遍历方法获得,可以利用这个特性,为独享定义一些私有但又只希望
    内部使用的方法
    var size = Symbol('size') 
            class Collection{
                constructor(){
                    this[size]=0
                }
                add(item){
                    this[this[size]]=item
                    this[size]++
                }
                static sizeOf(instance){
                    return instance[size]
    
                }
            }
            var x = new Collection() //Collection {Symbol(size): 0}
            Collection.sizeOf(x) //0
            x.add('foo')  // Collection {0: "foo", Symbol(size): 1}
            Collection.sizeOf(x) //1
            Object.keys(x) // ['0']
            Object.getOwnPropertyNames(x) //['1']
            Object.getOwnPropertySymbols(x) //[Symbol(size)]
    
    

    内置的Symbol值

    Symbol.hasInstance

    对象的Symbol.hasInstance属性指向内部一个方法,对象使用instanceOf运算符时会调用这个方法,判断对象是否是
    某个构造函数的实例eg. foo instanceof Foo 在语言内部实际调用的是Foo[Symbol.hasInstance](foo)
    

    Symbol.isConcatSpreadable

    对象的Symbol.isConcatSpreadable属性等于一个布尔值,表示该对象使用Array.property.concat()时是否可以展开
       let Arr1 = [1,2,3]
          let Arr2 = [3,4]
          var Arr3 = Arr1.concat(Arr2) //[1, 2, 3, 3, 2]
          let Arr4 = [5,6]
          Arr4[Symbol.isConcatSpreadable]= false
          let Arr5 = Arr1.concat(Arr4) //[1, 2, 3, Array(2)]
    

    Symbol.species

    对象的Symbol.species属性指向一个方法对象创造实例的时候会调用this.constructor[Symbol.species]存在
    就会使用这个属性作为构造函数来创建新的实例对象
    Symbol,species属性默认的读取器如下
    static get [Symbol.species](){
      return this
    }
    

    Symbol.match

    对象的Symbol.match属性指向一个函数,当执行str.match(myObject)时,如果改属性存在,会调用它返回该方法的返回值
    String.property.macth(regexp)===>regexp[Symbol.macth](this)
    

    Symbol.replace

    对象的replace属性指向一个方法,当String.property.replace方法调用时会返回该方法的返回值
    String.property.replace(searchValue,replaceValue) ==> searchValue[Symbol.replace](this,replaceValue)
    

    Symbol.search

    对象的Symbol.search属性指向一个方法,当对象被String.property.search方法调用时会返回该方法的返回值
    String,property.search(regexp) ==> regexp[Symbol.search](this)
    

    Symbol.split

    对象的Symbol.split属性指向一个方法,当对象被String.property.split方法调用时会返回该方法的返回值
    String,property.search(separator,limit) ==> regexp[Symbol.search](this,limit)
    

    Symbol.iterator

    对象的Symbol.split属性指向其默认的遍历器方法,即对象在进行for...of循环时调用这个方法,返回该对象的默认遍历器
    

    Symbol.toPrimitive

    对象的Symbol.toPrimitive属性指向一个方法,对象被转为原始类型的时候会调用这个方法,返回该对象对应的原始值
    
  • 相关阅读:
    ctfhub技能树—文件上传—双写后缀
    ctfhub技能树—文件上传—00截断
    ctfhub技能树—文件上传—文件头检查
    ctfhub技能树—文件上传—MIME绕过
    ctfhub技能树—文件上传—.htaccess
    ctfhub技能树—文件上传—前端验证
    ctfhub技能树—文件上传—无验证
    ctfhub技能树—sql注入—Refer注入
    ctfhub技能树—sql注入—UA注入
    面试中被问到的知识点
  • 原文地址:https://www.cnblogs.com/rainbowqq/p/14749317.html
Copyright © 2020-2023  润新知