你真的了解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 天,点击查看活动详情