在es5中有五種基本類型分別是字符串,數字,布爾,null
和 undefined
,在es6中引入一種新的基本類型 Symbol
,表示獨一無二的值。經常使用於模擬建立對象的私有屬性。html
調用全局函數 Symbol
建立,該函數接收一個字符串做爲描述參數:es6
let sb = Symbol('sb');
console.log(sb); // Symbol(sb)
console.log(typeof sb); // symbol
複製代碼
不能使用 new
調用,由於 Symbol
是基本類型,不是返回對象。函數
由於 Symbol
自己表示獨一無二的值,因此兩個相同描述的 Symbol
是不相等的:post
let sb = Symbol('sb');
let sb2 = Symbol('sb');
console.log(sb === sb2); // false
複製代碼
對象做爲描述會先調用對象的 toString
方法:ui
let obj = {
toString() {
return 'Symbol obj';
}
};
let sb = Symbol(obj);
console.log(sb); // Symbol(Symbol obj)
複製代碼
不能經過運算強制轉換爲字符串和數字:this
let sb = Symbol('sb');
let desc = sb + ''; // Cannot convert a Symbol value to a string
let num = sb + 1; // Cannot convert a Symbol value to a number
複製代碼
有時候咱們須要用到同一個 Symbol
來作一些處理,就要用到 Symbol.for
方法來註冊一個全局的 Symbol
:es5
let sb = Symbol.for('sb');
let sb2 = Symbol.for('sb');
let obj = {
[sb]: '12345'
};
console.log(obj[sb]); // 12345
console.log(sb === sb2); // true
console.log(obj[sb2]); // 12345
複製代碼
調用該方法會先在全局的Symbol註冊表中查找有沒有鍵爲'sb'的 Symbol
,若是存在則返回。不存在就先建立一個新的 Symbol
,並在全局表中註冊。spa
Symbol.keyFor
方法返回在Symbol全局註冊表中檢索與該 Symbol
有關的key:prototype
let sb = Symbol.for('sb');
console.log(Symbol.keyFor(sb)); // sb
let sb2 = Symbol('sb');
console.log(Symbol.keyFor(sb2)); // undefined
複製代碼
用 Symbol
做爲對象的屬性沒法在 Object.keys
和Object.getOwnPropertyNames
方法返回,es6提供一個Object.getOwnPropertySymbols
方法來返回對象全部的 Symbol
屬性。code
let sb = Symbol('sb');
let obj = {
[sb]: '12345'
};
let symbols = Object.getOwnPropertySymbols(obj);
console.log(symbols); // [ Symbol(sb) ]
console.log(obj[symbols[0]]); // 12345
複製代碼
es6提供了一些內置的 Symbol
變量,用於改變js中某些行爲。好比設置構造函數的Symbol.hasInstance
能夠自定義 instanceof
的行爲:
function SpecialNumber() {
//
}
Object.defineProperty(SpecialNumber, Symbol.hasInstance, {
value: function(v) {
return v instanceof Number && (v >= 1 && v <= 100);
}
});
let zero = new Number(0),
two = new Number(2);
console.log(zero instanceof SpecialNumber); // false
console.log(two instanceof SpecialNumber); // true
複製代碼
Symbol.toStringTag
能夠改變調用 Object.prototype.toString
方法的默認行爲:
function Person(name) {
this.name = name;
}
Person.prototype[Symbol.toStringTag] = 'Person';
Person.prototype.toString = function() {
return this.name;
};
const person = new Person('wozien');
console.log(Object.prototype.toString.call(person)); // [object Person]
console.log(person.toString()); // wozien
複製代碼
其餘內置的Symbol及用法參考MDN文檔
做爲對象的屬性和方法,模擬對象的私有化:
let myKey = Symbol();
let myFunc = Symbol();
let obj = {
[myKey]: '123',
[myFunc]() {
return 'bar';
}
};
console.log(obj[myKey]); // 123
console.log(obj[myFunc]()); // bar
複製代碼
定義常量,防止常量重複定義:
const COLOR_RED = Symbol('red');
const COLOR_BLUR = Symbol('blue');
const COLOR_PINK = Symbol('pink');
switch (color) {
case COLOR_RED:
break;
case COLOR_BLUR:
break;
//
}
複製代碼
** 做爲類型的私有屬性 ** 。防止定義的衝突和外部訪問:
const PASSWORD = Symbol();
class Login {
constructor(name, password) {
this.name = name;
this[PASSWORD] = password;
}
hasPassword(pw) {
return this[PASSWORD] === pw;
}
}
複製代碼
** 自定義對象的迭代行爲 ** :
let obj = {
data: ['hello', 'world'],
[Symbol.iterator]() {
const self = this;
let index = 0;
return {
next() {
if (index < self.data.length) {
return {
value: self.data[index++]
};
} else {
return { done: true };
}
}
};
}
};
for (let x of obj) {
console.log(x);
}
// hello
// world
複製代碼