作者:xiaohesong
連接:https://juejin.im/post/6844903703242080263
原文連結:https://xiaohesong.gitbook.io/today-i-learn/front-end/es6/understanding-es6/symbol#basic
來源:掘金
Symbol是ES6加進來的,也是屬於基本類型(number、string....)
可以發現Symbol類型可以當作對象的key
let foo = Symbol('bar')
console.log(typeof foo) // 'symbol'
let testObj = {}
testObj[foo] = '這樣可以設置!'
console.log(testObj);
透過這個方法創建時會先在全局裡面尋找這個key的Symbol,如果存在則返回此Symbol,不存在則創建並進行全局註冊
// 用基本方法創建兩個相同key的Symbol會不一樣
let first = Symbol('不會一樣')
let second = Symbol('不會一樣')
console.log(first === second); // fasle
// 用此方法創建的則會一樣
let fooA = Symbol.for('居然會一樣')
let fooB = Symbol.for('居然會一樣')
console.log(fooA === fooB); // true
// 基礎方法跟Symbol.for當然也不一樣
let barA = Symbol('這樣也會不一樣')
let barB = Symbol.for('這樣也會不一樣')
console.log(barA === barB); // false
返回用全局註冊Symbol的key
let fooA = Symbol.for("foo");
console.log(Symbol.keyFor(fooA)); // "foo"
let fooB = Symbol.for("foo");
console.log(Symbol.keyFor(fooB)); // "foo"
// 因為沒有透過Symbol.for進行全局註冊當然找不到
let notKeyCreated = Symbol("我居然會不存在!");
console.log(Symbol.keyFor(notKeyCreated)); // undefined
可以透過String轉型,不過講真的這樣做意義不大
let foo = Symbol('foo')
console.log(String(foo));
console.log(foo.toString())
console.log(foo + '');
let foo = Symbol('foo')
let obj = {
// 注意我們要用Symbol當成key,需要要用方括號刮起來
// 因為需要的是變量foo非字符串foo
[foo]: 'foo'
}
console.log(Object.keys(obj)) // []
console.log(Object.getOwnPropertyNames(obj)) // []
// ES6新增的方法
console.log(Object.getOwnPropertySymbols(obj)) // [Symbol(foo)]
let obj = {
[foo]: 'foo'
}
這裡提到了我們要讓
注意我們要用Symbol當成key,需要用方括號刮起來
因為需要的是變量foo非字符串foo
所以以下設置也是為了此目的
let obj = {}
let foo = Symbol('foo')
obj.foo = 'foo'
obj[foo] = 'SymbolFoo'
console.log(obj);
每一個函數內部都會有存在這個方法,主要判斷一個對象是否為構造函數的實例(即是instanceof)
function User() {}
const Mike = new User
console.log(Mike instanceof User) // true
// 使用函數內部的方法
console.log(User[Symbol.hasInstance](Mike)) // true
// 取自MDN
class Array1 {
static [Symbol.hasInstance](instance) {
return Array.isArray(instance);
}
}
console.log([] instanceof Array1);
// expected output: true
以下取自MDN:
內置的方法的參數時是否展開其數組元素。
Symbol.isConcatSpreadable
`符号用于配置某对象作为Array.prototype.concat
let foo = ['a', 'b', 'c']
let = numeric = [1, 2, 3];
let fooAndNumericA = foo.concat(numeric);
console.log(fooAndNumericA); // 结果: ['a', 'b', 'c', 1, 2, 3]
//
numeric[Symbol.isConcatSpreadable] = false;
let fooAndNumericB = foo.concat(numeric)
console.log(fooAndNumericB);
對象的內置屬性,一個對象可以被轉換成原始值都是靠他幫忙
該函數被調用時,會被傳遞hint參數,代表預期想要轉換的類型
參數的值有三種
- number
- string
- default
number mode:
- 首先調用
valueOf
,若是原始類型,那就返回。- 若非原始值,那麼就調用
toString
,如果是原始類型,那就返回- 如果都不存在,那麼就報錯
string mode 在字符串的情況下,行為略有不同(優先級從高到低)
- 首先調用
toString
,如果是原始值,那麼就返回- 如果前面不是原始值,那麼就嘗試調用
valueOf
,如果是原始值,那麼就返回- 拋出錯誤
此例子可以觀察Symbol.toPrimitive是如何干擾對象轉換成原始類型
// 以下改寫自MDN
// 沒有改寫 Symbol.toPrimitive 的對象
var fooA = {};
console.log(fooA / 1); // NaN
console.log(String(fooA)); // "[object Object]"
console.log(fooA + ""); // "[object Object]"
// 聲明一個新的對象,並更改了他的 Symbol.toPrimitive 屬性
var fooB = {
[Symbol.toPrimitive](hint) {
if (hint == "number") {
return 'number';
}
if (hint == "string") {
return "string";
}
return 'default';
}
};
console.log(fooB / 1); // Nan
console.log(String(fooB)); // string
console.log(fooB + ""); // default