你真的了解symbol嘛?
在我刚学JavaScript的时候,Symbol这种数据类型确实没有特别在意过,项目中很少使用。直到再次了解JavaScript之时,这次才刻意的注意到了Symbol。下面我们就来详细的了解一下symbol。
symbol是什么?
Symbol是 JavaScript 中的一种数据类型,它是独一无二且不可改变的值。它们可以用作对象属性的键,因为它们总是独一无二的。每个 Symbol 都有一个描述,但是它不是用于识别该 Symbol 的,而只是为了调试目的。
使用语法:Symbol([description])
,其中 description
是可选的字符串,描述 Symbol 的目的。
const symbol1 = Symbol();
const symbol2 = Symbol('symbol2');
console.log(typeof symbol1); // "symbol"
console.log(symbol1.toString()); // "Symbol()"
console.log(symbol2.toString()); // "Symbol(symbol2)"
symbol的基础用法
1.创建一个 符号
const symbol = Symbol('symbol');
2.使用 Symbol 值作为对象键:
const obj = { [symbol]: 'value' };
console.log(obj[symbol]); // "value"
3.使用 'typeof
console.log(typeof symbol); // "symbol"
4.使用 'Object.get'获取对象的所有 Symbol 键:
const symbol1 = Symbol('symbol1');
const symbol2 = Symbol('symbol2');
const obj = { [symbol1]: 'value1', [symbol2]: 'value2' };
console.log(Object.getOwnPropertySymbols(obj)); // [Symbol(symbol1), Symbol(symbol2)]
5.使用 'Symbol.for'
const symbol1 = Symbol.for('symbol');
const symbol2 = Symbol.for('symbol');
console.log(symbol1 === symbol2); // true
6.使用Symbol.keyFor
获取全局 Symbol 的标识符: `
const symbol = Symbol.for('symbol');
console.log(Symbol.keyFor(symbol)); // "symbol"
以上是 Symbol 类型的基本用法,其中:
- 创建 Symbol 值时,可以通过传入字符串参数来为 Symbol 添加描述信息;
- 使用 Symbol 值作为对象键时,可以保证该键的唯一性,防止与其他键冲突;
- 'Object.getOwnPropertySymb方法可以用来获取对象的所有 Symbol 键;
- 使用
Symbol.for
创建的全局 Symbol 值可以在多处使用,并且总是相等; Symbol.keyFor
方法可以用来获取全局
symbol的常用内置符号
Symbol.iterator
Symbol.iterator
是一个内置的 Symbol 值,用于定义对象的默认遍历器(default iterator)。
当使用 for...of 循环遍历一个对象时,如果该对象定义了 Symbol.iterator
属性,则该属性的值会被用作该对象的默认遍历器。
举个例子:
let myArray = [1, 2, 3];
let it = myArray[Symbol.iterator]();
console.log(it.next()); // { value: 1, done: false }
console.log(it.next()); // { value: 2, done: false }
console.log(it.next()); // { value: 3, done: false }
console.log(it.next()); // { value: undefined, done: true }
上面代码中,我们使用 Symbol.iterator
访问了数组的默认遍历器,并通过遍历器逐一遍历了数组的元素。
Symbol.toStringTag
Symbol.toStringTag
是一个内置的 Symbol 值,用于定义对象的字符串表现形式。
通过设置对象的 Symbol.toStringTag
属性,开发人员可以控制该对象在使用 Object.prototype.toString.call
方法时的字符串输出。
例如:
class MyClass {
get [Symbol.toStringTag]() {
return 'MyClass';
}
}
let myObj = new MyClass();
console.log(Object.prototype.toString.call(myObj));
// '[object MyClass]'
上面代码中,我们定义了一个类 MyClass
,并通过设置 Symbol.toStringTag
属性,使得该类的实例在调用 Object.prototype.toString
方法时,输出的字符串为 [object MyClass]
。
Symbol.hasInstance
Symbol.hasInstance
是一个内置的 Symbol 值,用于定义一个类的实例判定方法。
通过设置类的 Symbol.hasInstance
属性,开发人员可以自定义类的实例判定逻辑,并控制 instanceof
运算符的行为。
例如:
class MyClass {
static [Symbol.hasInstance](instance) {
return instance.num === 42;
}
}
let myObj = { num: 42 };
console.log(myObj instanceof MyClass); // true
上面代码中,我们定义了一个类 MyClass
,并通过设置 Symbol.hasInstance
属性,控制了该类的实例判定逻辑。当一个对象的 num
属性为 42 时,它就是 MyClass
的实例,因此 myObj instanceof MyClass
的结果为 true
。
Symbol.species
Symbol.species
是一个内置的 Symbol 值,用于指定一个对象的构造函数,在该对象作为某个方法的返回值时,用于构造新的对象。
通过设置类的 Symbol.species
属性,开发人员可以控制该类的衍生类,以适应多种使用场景。
例如:
class MyArray extends Array {
static get [Symbol.species]() {
return Array;
}
}
let myArr = new MyArray(1, 2, 3);
let mappedArr = myArr.map(x => x * x);
console.log(mappedArr instanceof MyArray); // false
console.log(mappedArr instanceof Array); // true
上面代码中,我们定义了一个类 MyArray
,继承自内置类 Array
。并通过设置 Symbol.species
属性,使得该类的衍生类为 Array
。当调用 myArr.map
方法后,返回的 mappedArr
对象为内置类 Array
的实例,而非 MyArray
的实例。
Symbol.isConcatSpreadable
Symbol.isConcatSpreadable
是一个内置的 Symbol 值,用于指定一个对象在 Array.prototype.concat
方法中是否可以展开。
当一个对象的 Symbol.isConcatSpreadable
属性为 true
时,该对象在 Array.prototype.concat
方法中会被展开,否则该对象会作为一个整体被添加到新数组的末尾。
例如:
let arr1 = [1, 2, 3];
let arr2 = [4, 5, 6];
let arr3 = [7, 8, 9];
arr2[Symbol.isConcatSpreadable] = false;
let newArr = arr1.concat(arr2, arr3);
console.log(newArr); // [1, 2, 3, [4, 5, 6], 7, 8, 9]
上面代码中,我们定义了三个数组 arr1
、arr2
、arr3
,并将 arr2
的 Symbol.isConcatSpreadable
属性设置为 false
。调用 Array.prototype.concat
方法后,arr2
不会被展开,而作为一个整体被添加到新数组的末尾。
Symbol.unscopables
Symbol.unscopables
是一个内置的 Symbol 值,它是一个对象属性,指定了该对象的哪些属性不能被 with 语句查找到。
例如:
let obj = {a: 1, b: 2};
obj[Symbol.unscopables] = {a: false, b: true};
with (obj) {
console.log(a); // 1
console.log(b); // ReferenceError: b is not defined
}
上面代码中,我们定义了一个对象 obj
,并将它的 Symbol.unscopables
属性设置为 {a: false, b: true}
。在 with 语句中,a
属性可以被查找到,但 b
属性不能被查找到,将会导致错误。
另外,其他更多Symbol属性和特性可以查阅相关文档和书籍。
开启掘金成长之旅!这是我参与「掘金日新计划 · 2 月更文挑战」的第 1 天,点击查看活动详情