据说最近面试有人问Symbol

Symbol

ES6新增长的基本数据类型,表示独一无二。所以js的基本数据类型都包括(number,string,boolean,null,undefined,symbol)编程

【1】永远不相等

let s1 = Symbol();
let s2 = Symbol();
console.log(s1 === s2); // false
复制代码

【2】建立是能够增长标识

通常增长string或者number的标识。由下列能够看出s3虽然增长了{a:2}对象做为标识,可是在建立的时候也先调用了toString方法转换成了string类型,所以为了不隐式类型转换报错咱们在建立的时候传入的标识值通常传string或者number数组

let s1 = Symbol('GuYan');
let s2 = Symbol(1);
let s3 = Symbol({a:2});
console.log(s1); // Symbol(GuYan)
console.log(s2); // Symbol(1)
console.log(s3); // Symbol([object Object])
复制代码

【3】声明的属性不可枚举

let s1 = Symbol('GuYan');
let obj = {
    [s1]:1,
    s1:2
}
for(let key in obj){
    console.log(obj[key]); // 2
}
复制代码

【4】经过特有的方法Object.getOwnPropertySymbols来获取Symbol声明的属性

在【3】中咱们发现知道经过Symbol定义的对象属性是不可枚举的,可是咱们有想操做这个属性的时候就能够经过Object.getOwnPropertySymbols来获取ide

let s1 = Symbol('GuYan');
let obj = {
    [s1]:1,
    s1:2
}
console.log(Object.getOwnPropertySymbols(obj)); // [Symbol(GuYan)]
复制代码

【5】Symbol.for声明

在【1】中咱们知道,经过Symbol声明的变量是永远不相等的,可是咱们可能在开发过程当中遇到须要两个甚至多个地方公用一个惟一的值的时候,所以就须要咱们使用另外一种声明方式声明。post

工做原理:先判断这个变量是否已经声明,若是没有声明就建立一个这个变量,已经存在了获取这个变量的值进行赋值ui

let s1 = Symbol.for('GuYan'); // 没有这个变量声明一个
let s2 = Symbol.for('GuYan'); // 已经存在了,获取值进行赋值
console.log(s1 === s2) // true;
复制代码

【6】Symbol.keyFor()

获取Symbol的标识,只有经过Symbol.for()建立的变量才能经过这个方法获取spa

let s1 = Symbol.for('GuYan');
let s2 = Symbol('GuYan');
console.log(Symbol.keyFor(s1)); // GuYan
console.log(Symbol.keyFor(s2)); // undefined
复制代码

【7】元编程(对原生js操做进行修改)

  • 【7-1】Symbol.iterator实现对象的遍历(传送门
  • 【7-2】Symbol.hasInstance实现对instanceof的修改
    let instance = {};
    console.log({a:1} instanceof instance);// TypeError: Right-hand side of 'instanceof' is not callable
    ------------------------------------------------
    let instance = {
        [Symbol.hasInstance](value){
            console.log(value) // {a: 1}
            return 'a' in value;
        }
    }
    console.log({a:1} instanceof instance); // true
    复制代码
  • 【7-3】Symbol.isConcatSpreadable数组拼接的时候是否展开
    let arr = [1,2,3];
    console.log([].concat(arr,[4,5,6])); // [1, 2, 3, 4, 5, 6]
    ------------------------------------------------
    let arr = [1,2,3];
    arr[Symbol.isConcatSpreadable]  = false;
    console.log([].concat(arr,[4,5,6]));//[[1, 2, 3, Symbol(Symbol.isConcatSpreadable): false],4,5,6]
    复制代码
  • 【7-4】Symbol.matchSymbol.splitSymbol.searchSymbol.replace
    let obj = {};
    console.log('123'.match(obj)); // null
    ----------------------------------------------
    let obj = {
        [Symbol.match](value){
            console.log(value); // 123
            return value.length === 3;
        }
    }
    console.log('123'.match(obj));// true
    复制代码
  • 【7-5】Symbol.species衍生对象
    class MyArray extends Array{
        constructor(...args){
            super(...args)
        }
    }
    let v = new MyArray(1,2,3);
    let c = v.map(item=>item*=2); // c是v的衍生对象
    console.log(v instanceof MyArray); // true
    console.log(v instanceof Array); // ture
    console.log(c instanceof MyArray); // ture
    console.log(c instanceof Array); // true
    ----------------------------------------------
    class MyArray extends Array{
    constructor(...args){
        super(...args)
    }
    // 强制修改衍生对象的指向
    static get [Symbol.species]() { // 静态属于类本身的
         return Array;
     }
    }
    let v = new MyArray(1,2,3);
    let c = v.map(item=>item*=2); // c是v的衍生对象
    console.log(v instanceof MyArray); // true
    console.log(v instanceof Array); // true
    console.log(c instanceof MyArray); // false
    console.log(c instanceof Array); // true
    复制代码
  • 【7-6】Symbol.toPrimitive数据类型转化
    let obj = {};
        console.log(obj + ''); // [object Object]
        console.log(Number(obj)); // NaN
        console.log(+obj); // NaN
        -------------------------------------------
        let obj = {
            [Symbol.toPrimitive](type){
                return 123;
            }
        }
        console.log(obj + ''); // '123'
        console.log(Number(obj)); // 123
        console.log(+obj); // 123
    复制代码
  • 【7-7】Symbol.toStringTag修改toString方法
    let obj = {};
    console.log(Object.prototype.toString.call(obj));//[object,Object]
    console.log(obj+''); // [object,Object]
    --------------------------------------------------------------
    let obj = {
        [Symbol.toStringTag]:'GuYan'
    }
    console.log(Object.prototype.toString.call(obj)); // [object GuYan]
    console.log(obj + ''); // [object GuYan]
    复制代码
  • 【7-8】Symbol.unscopables不在做用域中的
    let arr = [];
    console.log(arr[Symbol.unscopables]);//{copyWithin: true,entries: true,fill: true,find: true,findIndex: true,flat: true,flatMap: true,flatten: true,includes: true,keys: true,values: true}
    Object.keys(Array.prototype[Symbol.unscopables]);//["copyWithin", "entries", "fill", "find", "findIndex", "flat", "flatMap", "includes", "keys", "values", "flatten"]
    // 说明,数组有 11 个属性,会被with命令排除。
    ----------------------------------------------------------------------------
    class MyArry extends Array{
      constructor(...args) {
        super(...args);
      }
    }
    let arr = new MyArry();
    console.log(arr[Symbol.unscopables]);//{copyWithin: true,entries: true,fill: true,find: true,findIndex: true,flat: true,flatMap: true,flatten: true,includes: true,keys: true,values: true}
    with (arr) {
      console.log(find); // find is not defined
    }
    ----------------------------------------------------------------------------
      class MyArry extends Array{
      constructor(...args) {
        super(...args);
      }
      get [Symbol.unscopables]() {
        return {find:false};
      }
    }
    let arr = new MyArry();
    console.log(arr[Symbol.unscopables]); // {find:false}
    with (arr) {
      console.log(find); // [Function: find]
    }
    复制代码
相关文章
相关标签/搜索