在 ES6 中,新增了一种原始数据类型 Symbol,它可以用来创建唯一的标识符,解决属性名冲突的问题。本文将详细介绍 Symbol 的使用方法,包括创建 Symbol、Symbol 的属性和方法、Symbol 与对象的关系等方面,并提供实际应用示例。
创建 Symbol
在 ES6 中,我们可以使用 Symbol 函数来创建一个 Symbol,其语法如下:
let s = Symbol(description);
其中,description 表示可选的描述符,用来标识这个 Symbol。可以使用 toString 方法查看 Symbol 的描述符,例如:
let s = Symbol('foo'); console.log(s.toString()); // 输出:"Symbol(foo)"
需要注意的是,Symbol 的描述符并不是 Symbol 值的名称,不能像其他类型的属性一样访问。如果想要访问 Symbol 值,需要使用 Symbol 对象,例如:
let s = Symbol('foo'); let obj = { [s]: 'bar' }; console.log(obj[s]); // 输出 "bar" console.log(obj.foo); // 输出 "undefined"
Symbol 的属性和方法
Symbol 类型有以下常用属性和方法:
Symbol.iterator
一个函数,返回该对象默认的迭代器。可以使用 for...of 循环来遍历一个对象,默认情况下会调用 Symbol.iterator 方法。
let arr = [1, 2, 3]; let iter = arr[Symbol.iterator](); for (let i of iter) { console.log(i); } // 输出 1 2 3
Symbol.hasInstance
一个函数,用来判断是否为某个构造函数的实例。
class MyClass { static [Symbol.hasInstance](obj) { return obj instanceof Array; } } console.log([] instanceof MyClass); // 输出 true console.log({} instanceof MyClass); // 输出 false
Symbol.isConcatSpreadable
一个布尔值,表示该对象在使用 Array.prototype.concat() 方法时是否展开。
let arr1 = [1, 2, 3]; let arr2 = [4, 5, 6]; console.log(arr1.concat(arr2)); // 输出 [1, 2, 3, 4, 5, 6] arr2[Symbol.isConcatSpreadable] = false; console.log(arr1.concat(arr2)); // 输出 [1, 2, 3, [4, 5, 6]]
Symbol.species
一个函数,用来创建派生对象的构造函数。
// javascriptcn.com 代码示例 class MyArray extends Array { static get [Symbol.species]() { return Array; } } let arr = new MyArray(1, 2, 3); let clone = arr.slice(); console.log(clone instanceof MyArray); // 输出 false console.log(clone instanceof Array); // 输出 true
Symbol 与对象的关系
我们可以使用 Symbol 为对象添加新的属性,避免与已有属性命名冲突。
const name = Symbol('name'); const person = { [name]: 'Tom' }; console.log(person[name]); // 输出 "Tom"
除此之外,我们可以使用 Symbol 作为属性名,使得该属性不会被 for...in、Object.keys 和 JSON.stringify 等方法枚举。例如:
// javascriptcn.com 代码示例 const hidden = Symbol('hidden'); const obj = { name: 'Tom', [hidden]: 'This property is hidden' }; for (let key in obj) { console.log(key); // 输出 "name" } console.log(Object.keys(obj)); // 输出 ["name"] console.log(JSON.stringify(obj)); // 输出 "{"name":"Tom"}"
实际应用示例
我们可以使用 Symbol 来创建一个只读属性,例如:
// javascriptcn.com 代码示例 const readOnly = Symbol('readOnly'); const obj = {}; obj[readOnly] = true; Object.defineProperty(obj, 'prop', { get: function() { return this[readOnly]; } }); console.log(obj.prop); // 输出 true obj.prop = false; console.log(obj.prop); // 输出 true
另外,我们可以使用 Symbol 来创建一些方法,例如:
// javascriptcn.com 代码示例 const shape = Symbol('shape'); class Circle { constructor(radius) { this.radius = radius; } [shape]() { return 'circle'; } diameter() { return this.radius * 2; } } const c = new Circle(10); console.log(c[shape]()); // 输出 "circle" console.log(c.diameter()); // 输出 20
使用 Symbol 还可以创建一个全局的命名空间,避免不同模块之间的变量名冲突:
const myModule = {}; myModule[Symbol('privateVar')] = 'This variable is private'; myModule.foo = function() { console.log(this[Symbol('privateVar')]); }; myModule.foo(); // 输出 "undefined"
总结
Symbol 是 ES6 中新增的一种原始数据类型,用来创建唯一的标识符,可以解决属性名冲突的问题。本文详细介绍了 Symbol 的创建方法、属性和方法,并提供了实际应用示例。在实际编程中,我们可以灵活运用 Symbol 来提高代码的可读性和健壮性。
来源:JavaScript中文网 ,转载请注明来源 本文地址:https://www.javascriptcn.com/post/652c094f7d4982a6ebde2581