據說最近面試有人問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]
    }
    複製代碼
相關文章
相關標籤/搜索