前言
Symbol 是 ECMAScript 2015 引入的新类型,用于表示独一无二的值。在 ECMAScript 2016 中,Symbol 又进行了一些扩展和改进。本文将详细介绍 Symbol 的概念、用法和实践应用,希望对前端开发者有所帮助。
Symbol 的概念
Symbol 是一种新的原始数据类型,表示独一无二的值。它的概念类似于 Java 中的枚举类型,但更加灵活和强大。
Symbol 的定义方式如下:
let sym = Symbol();
其中,let
是 ES6 中新增的块级作用域声明关键字,Symbol()
是 Symbol 的构造函数,用于创建一个新的 Symbol 值。每个 Symbol 值都是唯一的,即使创建时传入的参数相同。
Symbol 支持传入一个字符串作为参数,用于描述该 Symbol 的名称。这个名称只是一个描述符,不会影响 Symbol 的唯一性。例如:
let sym1 = Symbol('foo'); let sym2 = Symbol('foo'); console.log(sym1 === sym2); // false
上述代码中,sym1
和 sym2
都是 Symbol 类型的值,但它们是不同的值,因为它们的名称不同。
Symbol 的另一个特点是不可枚举。这意味着它们不会出现在 for...in 循环中,也不会被 Object.keys() 和 JSON.stringify() 等方法包含。
Symbol 的用法
Symbol 主要用于两个方面:作为对象属性的键和作为私有成员变量。下面分别介绍这两个用法。
1. 作为对象属性的键
在 ES6 之前,我们通常使用字符串作为对象属性的键。但是,字符串作为键有一个缺点,就是容易重复。如果两个对象都有相同的属性名,那么它们就会相互覆盖,导致数据错误。
Symbol 的出现解决了这个问题。由于每个 Symbol 都是唯一的,所以可以用它作为对象属性的键,避免属性名冲突。例如:
let obj = { [Symbol('foo')]: 'foo value', [Symbol('bar')]: 'bar value' }; console.log(obj); // {Symbol(foo): "foo value", Symbol(bar): "bar value"}
上述代码中,obj
是一个对象,它有两个属性,分别用 Symbol 类型的值作为键。这两个属性都是不可枚举的,因此无法通过 for...in 循环或 Object.keys() 方法访问到。
2. 作为私有成员变量
在传统的面向对象编程中,我们通常将对象的私有成员变量定义为对象的属性,并使用下划线开头来表示它们是私有的。但是,这种做法并不严格,因为外部仍然可以通过对象的属性访问到私有成员变量。
Symbol 的出现可以解决这个问题。我们可以将私有成员变量定义为对象的 Symbol 属性,这样外部就无法访问到它们。例如:
let obj = { [Symbol('privateData')]: 'private data' }; console.log(obj[Symbol('privateData')]); // undefined
上述代码中,obj
是一个对象,它有一个名为 Symbol('privateData') 的属性,该属性存储了私有数据。由于该属性是不可枚举的,因此外部无法访问到它。只有对象内部的方法才能访问到这个私有数据。
Symbol 的实践应用
除了上述两个用法之外,Symbol 还有一些实践应用。下面分别介绍这些应用。
1. Symbol.iterator
ES6 引入了一种新的遍历器接口,可以用于遍历数据结构中的元素。这个接口定义在 Symbol.iterator 属性中,每个数据结构都可以实现这个接口,从而支持遍历。例如:
let arr = [1, 2, 3]; let iter = arr[Symbol.iterator](); console.log(iter.next()); // {value: 1, done: false} console.log(iter.next()); // {value: 2, done: false} console.log(iter.next()); // {value: 3, done: false} console.log(iter.next()); // {value: undefined, done: true}
上述代码中,arr
是一个数组,它实现了 Symbol.iterator 接口,从而支持遍历。通过调用 arrSymbol.iterator 方法,可以获取到一个遍历器对象 iter
,然后使用 iter.next()
方法依次遍历数组中的元素。
2. Symbol.for 和 Symbol.keyFor
Symbol.for 方法可以用于创建一个全局的 Symbol 值,该值可以被多个窗口或框架共享。例如:
let sym1 = Symbol.for('foo'); let sym2 = Symbol.for('foo'); console.log(sym1 === sym2); // true
上述代码中,sym1
和 sym2
都是全局的 Symbol 值,它们的名称相同,因此它们是相等的。
Symbol.keyFor 方法可以用于获取一个全局 Symbol 值的名称。例如:
let sym = Symbol.for('foo'); console.log(Symbol.keyFor(sym)); // 'foo'
上述代码中,Symbol.keyFor(sym)
方法返回的是全局 Symbol 值 sym
的名称。
总结
Symbol 是 ECMAScript 2015 引入的新类型,用于表示独一无二的值。它可以作为对象属性的键和私有成员变量,还可以用于实现遍历器接口和创建全局 Symbol 值。Symbol 的出现,解决了对象属性名冲突和私有成员变量访问问题,是一种非常实用的新特性。
来源:JavaScript中文网 ,转载请注明来源 https://www.javascriptcn.com/post/65ceb721add4f0e0ff8005d1