ES6新特征 之 Symbol
2019-08-14 本文已影响4人
前白
基本概念
Symbol:表示独一无二的值,属于类字符串数据类型,本质上可以当字符串来用。
基本用法
- Symbol是JavaScript的第七种数据类型,前六种分别是undefined、null、Boolean、String、NUmber、Objects、Symbol。
// 1 let symbol = Symbol(); typeof symbol // symbol // 2 Symbol使用时不能使用new,它是一个函数,可以接收参数,仅作为描述 let symbol1 = Symbol('week'); symbol1; // Symbol(week) symbol1.toString(); // "Symbol(week)" // 3 let symbol1 = Symbol(); let symbol2 = Symbol(); symbol1 === symbol2; // false let symbol1 = Symbol('object'); let symbol2 = Symbol('object'); symbol1 === symbol2; // false // 4 隐式转换 const obj = { toString() { return 'object'; } }; const symbol = Symbol(obj); symbol; // Symbol(object) // 5 不能参与运算 let symbol = Symbol('symbol'); "hello" + symbol; // TypeError: Cannot convert a Symbol value to a string // 6 类型转换 String(symbol); symbol.toString(); // Symbol(symbol) let symbol = Symbol(); Boolean(symbol); // true Number(symbol); // TypeError: Cannot convert a Symbol value to a number
- description ,Symbol的描述
const symbol = Symbol('symbollobmys'); symbol.description; // "symbol"
- symbol应用场景,对象属性名
let symbol = Symbol(); let a = {}; a[symbol] = 'Hello!'; let a = { [symbol]: 'Hello!' }; let a = {}; Object.defineProperty( a, symbol, { value: 'Hello!' } );
- 属性遍历
属性遍历中的for...in、for...of、Object.keys()、Object.getOwnPropertyNames()、JSON.stringify()都不会返回Symbol,它们会把Symbol过滤掉。但是我们可以有两种方法得到Symbol,一种是Object.getOwnPropertySymbols,另一种是Reflect.ownKeys。const obj = {}; let symbol1 = Symbol('symbol1'); let symbol2 = Symbol('symbol2'); obj[symbol1] = 'symbol1'; obj[symbol2] = 'symbol1'; Object.getOwnPropertySymbols(obj); // [Symbol(symbol1), Symbol(symbol2)] Reflect.ownKeys(obj); // [Symbol(symbol1), Symbol(symbol2)] // 可以作为非私有的内部方法
- Symbol.for(是唯一一个能让两个Symbol相等的),寻找全局的环境下某个描述下面的这个Symbol,如果找到某一个描述下的Symbol,那么就会返回这个Symbol,如果没有找到就会生成一个新的Symbol。简而言之就是,返回当前索引Symbol。
let symbol1 = Symbol.for('week'); let symbol2 = Symbol.for('week'); symbol1 === symbol2; // true
- Symbol.keyFor,返回已登记的Symbol的key
let symbol1 = Symbol.for("symbol1"); Symbol.keyFor(symbol1); // symbol1 let symbol2 = Symbol("week"); Symbol.keyFor(symbol2); // undefined
内置的Symbol
- Symbol.hasInstance,instanceof运算符调用
class MyClass { [Symbol.hasInstance](obj) { return obj instanceof Array; } } [1, 2, 3] instanceof new MyClass(); // true
- Symbol.isConcatSpreadable,控制数组concat是否展开
let array1 = [1, 2]; [3, 4].concat(array1, 5); // ['a', 'b', 'c', 'd', 'e'] array1[Symbol.isConcatSpreadable]; // undefined let array2 = [1, 2]; array2[Symbol.isConcatSpreadable] = false; [3, 4].concat(array2, 5); // [3, 4, [1, 2], 5]
- Symbol.species,为衍生类指定原型
class MyArray extends Array { } const one = new MyArray(1, 2, 3); const two = a.map(x => x); const three = a.filter(x => x = 1); b instanceof MyArray; // true c instanceof MyArray; // true class MyArray extends Array { static get [Symbol.species]() { return Array; } } const one = new MyArray(1, 2, 3); const two = a.map(x => x); const three = a.filter(x => x = 1); b instanceof MyArray; // false c instanceof Array; // true
- Symbol.match ,str.match调用
class Mather { [Symbol.match](string) { return 'hello world'; } } 'e'.match(new Mather()); // 'hello world'
- Symbol.replace,replace调用
const demo = {}; demo[Symbol.replace] = () => 'hello word'; 'Hello'.replace(demo, 'World'); // hello word
- Symbol.search
- Symbol.split
- Symbol.iterator,默认遍历器
const diyIterable = {}; diyIterable[Symbol.iterator] = function* () { yield 'hello'; yield 'word'; }; [...diyIterable]; // ['hello', 'word']
- Symbol.toPrimitive ,类型转换调用
let object = { [Symbol.toPrimitive](hint) { switch (hint) { case 'number': return 1; case 'string': return 'hello'; case 'default': return 'word'; default: throw new Error('Cannot convert'); } } }; 2 * object; // 2 3 + object; // '3word' object == 'word'; // true String(object); // hello
- Symbol.toStringTag , 指定[object Object]或[object Array]中object后面字符串
({ [Symbol.toStringTag]: 'Hello' }.toString()) // "[object Hello]"
- Symbol.unscopables , 指定被with排除的属性,with是一个语句,它可以扩展一个作用域链
// with语句 扩展一个语句的作用域链 var a, x, y; var r = 10; with (Math) { a = PI * r * r; x = r * cos(PI); y = r * sin(PI / 2); } class MyClass { week() { return 1; } get [Symbol.unscopables]() { return { week: true }; } } var week = function () { return 2; }; with (MyClass.prototype) { week(); // 2 }