ES6

Symbol

概述

ES6引進了一種新的原始數據類型Symbol表示獨一無二的值。它是JavaScript語言的第七種類型。
Symbol值是經過Symbol函數生成。這就是說,對象的屬性名吸納在能夠有兩種類型,一種是原來的字符串,另外一種就是新增的Symbol類型。凡是屬性名屬於Symbol類型,就都是獨一無二的,能夠保證不會與其餘屬性名衝突。數組

let s = Symbol();
alert(typeof s)  //Symbol

注意:函數

1.symbol函數不能使用new命令,不然會報錯
2.Symnol是一個原始類型的值,不是對象(不能添加屬性)
3.它是一種相似於字符串的數據類型

Symbol函數能夠接收一個字符串做爲參數,表示對Symbol實例的描述,主要是爲了在控制檯顯示,或者轉爲字符串時比較容易區分。
Symbol函數的參數只是表示對當前Symbol值的描述,所以相同參數的Symbol函數的返回值是不相等的。this

// 沒有參數的狀況
let s1 = Symbol();
let s2 = Symbol();
s1 === s2 // false

//有參數的狀況
let s1 = Symbol('foo')
let s1 = Symbol('bar')
s1 === s2 // false 
  
//若是參數是一個對象,就會調用改對象的toString方法,將其轉爲字符串,而後才生成一個Symbol值
const obj = {
    toString() {
        return 'abc';
    }
};
const sym = Symbol(obj);
sym // Symbol(abc)

做爲屬性名的Symbol

let mySymbol = Symbol();

// 第一種寫法
let a = {};
a[mySymbol] = 'Hello!';

// 第二種寫法
let a = {
  [mySymbol]: 'Hello!'
};

// 第三種寫法
let a = {};
Object.defineProperty(a, mySymbol, { value: 'Hello!' });

// 以上寫法都獲得一樣結果
a[mySymbol] // "Hello!"
a.mySymbol  // undefined  //做爲對象屬性名時,不能用點運算符。

a.mySymbol = 'Hello!';
a[mySymbol] // undefined
a['mySymbol'] // "Hello!"
//由於點運算符後面是字符串,因此不會讀取mySymbol做爲標識名所指代的那個值,致使a的屬性名其實是一個字符串,而不是一個 Symbol 值。

屬性名的遍歷

Symbol做爲屬性名,該屬性不會出如今for...in、for...of也不會被Object.keys()、Object.getOwnPropertyNames()、JSON.stringify()
返回。可是它也不是私有屬性。有一個Object。getOwnPropertySymbols方法,能夠獲取指定對象的全部Symbol屬性名。code

Object.getOwnPropertySymbol方法返回的是一個數組,成員是當前對象中全部用做屬性名的Symbol值。對象

const obj = {};

let foo = Symbol("foo");

Object.defineProperty(obj, foo, {
  value: "foobar",
});

for (let i in obj) {
  console.log(i); // 無輸出
}

Object.getOwnPropertyNames(obj)
// []

Object.getOwnPropertySymbols(obj)
// [Symbol(foo)]

另外一個新的 API,Reflect.ownKeys方法能夠返回全部類型的鍵名,包括常規鍵名和 Symbol 鍵名。ip

let obj = {
  [Symbol('my_key')]: 1,
  enum: 2,
  nonEnum: 3
};

Reflect.ownKeys(obj)
//  ["enum", "nonEnum", Symbol(my_key)]

因爲以Symbol值做爲名稱的屬性,不會被常規方法遍歷獲得。咱們能夠利用這個特性,爲對象定義一些非私有的,但又但願只用於內部的方法。字符串

let size = Symbol('size');
class Collection{
    constructor(){
        this[size] = 0;
    }
}
add(item){
    this[this[size]] = item;
    this[size]++;
}
static sizeOf(instance){
    return instance[size];
}

let x = new Collection();
Collection.sizeOf(x); //0

x.add('foo');
Collection.sizeOf(x) // 1

Object.keys(x) // ['0']
Object.getOwnPropertyNames(x) // ['0']
Object.getOwnPropertySymbols(x) // [Symbol(size)]
//對象x的size屬性是一個Symbol值,全部Object.key(x)、object.getOwnPropertyName(x)

symbol.for(),symbol.keyFor()

有時,咱們但願從新使用同一個Symbol值,symbol.for()方法能夠作到這一點。它接受一個字符串做爲參數,而後搜索有沒有以該參數做爲名稱的Symbol值。若是有,就返回這個Symbol值,不然就新建並返回一個以該字符串爲名稱的Symbol值。get

let s1 = Symbol.for('foo');
let s2 = Symbol.for('foo');
s1 === s2  //true

Symbol.for()與Symbol()這兩種寫法,都會生成新的Symbol,它們的區別是,前者會被登記在全局環境中供搜索,後者不會。Symbol.for()不會每次調用就返回一個新的Symbol類型的值,而是會先檢查給定的key是否已經存在,若是不存在纔會新建一個值。string

Symbol.for("bar") === Symbol.for("bar")
// true

Symbol("bar") === Symbol("bar")
// false

Symbol.keyFor方法返回一個已登記的symbol類型的keyit

let s1 = Symbol.for("foo");
Symbol.keyFor(s1) //"foo"

let 上 = Symbol("foo");
Symbol.keyFor(s2);  //undefined
相關文章
相關標籤/搜索
本站公眾號
   歡迎關注本站公眾號,獲取更多信息