1. 程式人生 > 實用技巧 >TypeScript Symbol型別

TypeScript Symbol型別

自ES6起,Symbol 成為了一種新的原生型別,symbol 型別的值是通過Symbol建構函式建立的。

// 建立 Symbol 型別變數
let s1 = Symbol();      // 引數可為空,接受任意型別引數
let s2 = Symbol('abc');
let s3 = Symbol('abc');
console.log(typeof s1)  // => symbol
console.log(s1 === s2)  // => false
console.log(s2 === s3)  // => false

應用場景一:使用Symbol來作為物件屬性名(key)

// 使用Symbol來作為物件屬性名(key)
let hobbyKey = Symbol();
let student = {
    age: 18,
    name: 'Jack'
}
student[hobbyKey] = 'Singing';
console.log(student);                   // => { age: 18, name: 'Jack', [Symbol()]: 'Singing' }
console.log(JSON.stringify(student));   // => {"age":18,"name":"Jack"}
let props = Object.getOwnPropertyNames(student);
console.log(props);                     // => [ 'age', 'name' ]

那應該如何獲取這些symbol key 對應的值?

// 使用Object的API
let allProps = Object.getOwnPropertySymbols(student)
console.log(allProps);              // => [Symbol()]
// 使用新增的反射API
let result = Reflect.ownKeys(student);
console.log(result);                // => [ 'age', 'name', Symbol() ]
console.log(student[result[2]]);    // => Singing

應用場景二:使用Symbol來替代常量

// 使用 Symbol型別,即能保證唯一,又省去命名的麻煩
const STATUS_UNPAID = Symbol()
const STATUS_PAID = Symbol()
const STATUS_FINISHED = Symbol()
function handleOrder(id: string, status) {
    switch (status) {
        case STATUS_UNPAID:
        // todo
        case STATUS_PAID:
        // todo
        case STATUS_FINISHED:
        // todo
        default:
            throw new Error('Unknown status')
    }
}

應用場景三:使用Symbol定義類的私有屬性/方法量

// a.ts
const PASSWORD = Symbol()
class Login {
    username: string
    constructor(username, password) {
        this.username = username
        this[PASSWORD] = password
    }
    checkPassword(pwd) {
        return this[PASSWORD] === pwd
    }
}
// b.ts
const login = new Login('admin', '123456')
login.checkPassword('123456')   // true
login.PASSWORD                  // undefined
login[PASSWORD]                 // undefined
login["PASSWORD"]               // undefined