ES6之原始数据类型Symbol
? 专栏介绍
在现代Web开发中,JavaScript已经成为了不可或缺的一部分。它不仅可以为网页增加交互性和动态性,还可以在后端开发中使用Node.js构建高效的服务器端应用程序。作为一种灵活且易学的脚本语言,JavaScript具有广泛的应用场景,并且不断发展演进。在本专栏中,我们将深入学习JavaScript语言的基本语法、DOM操作、事件处理、异步编程以及常见算法和数据结构等内容。此外,我们还将介绍ES6及其后续版本中引入的新特性,如箭头函数、模块化、解构赋值等。通过学习这些内容,你将能够成为一名熟练的JavaScript开发者,并能够应用这些知识来构建出高质量和可维护的Web应用程序。让我们一起开始JavaScript之旅吧!
引言
ES6 引入了一种新的原始数据类型Symbol
,表示独一无二的值。它属于 JavaScript 语言的原生数据类型之一,其他数据类型是:undefined
、null
、布尔值(Boolean)、字符串(String)、数值(Number)、大整数(BigInt)、对象(Object)。Symbol的作用是创建一个不可变且唯一的标识符,可以用作对象属性的键。它可以用来解决属性名冲突的问题,避免命名冲突。
概述
symbol 是一种基本数据类型。Symbol()
函数会返回 symbol 类型的值,该类型具有静态属性和静态方法。它的静态属性会暴露几个内建的成员对象;它的静态方法会暴露全局的 symbol 注册,且类似于内建对象类,但作为构造函数来说它并不完整,因为它不支持语法:“new Symbol()
”。
Symbol的原理是通过调用Symbol函数来创建一个新的Symbol值。每个通过Symbol函数创建的值都是唯一且不可变的。
基本用法
1. 创建一个唯一的属性键
const sym = Symbol();
const obj = {
[sym]: 'value'
};
console.log(obj[sym]); // value
2. 使用描述符创建一个带有描述信息的Symbol值
const sym = Symbol('description');
console.log(sym); // Symbol(description)
3. 使用全局注册表共享Symbol值
const sym1 = Symbol.for('key');
const sym2 = Symbol.for('key');
console.log(sym1 === sym2); // true
4. 获取已注册的全局Symbol键
const key = Symbol.keyFor(sym1);
console.log(key); // key
5. 遍历对象中所有使用了Symbol作为键名的属性
const sym = Symbol();
const obj = {
[sym]: 'value',
foo: 'bar'
};
for (let key in obj) {
console.log(key); // foo,不会输出sym
}
6. 使用内置的Well-known Symbols来自定义对象行为
class MyObject {
[Symbol.toStringTag]() {
return 'MyObject';
}
}
const obj = new MyObject();
console.log(obj.toString()); // [object MyObject]
7. 使用Symbol来定义类的私有属性
const _privateProperty = Symbol('private');
class MyClass {
constructor() {
this[_privateProperty] = 'private value';
}
getPrivateProperty() {
return this[_privateProperty];
}
}
const myObj = new MyClass();
console.log(myObj.getPrivateProperty()); // private value
console.log(myObj[_privateProperty]); // undefined
这些示例展示了Symbol的一些基本用法,包括创建唯一的属性键、使用描述符创建Symbol值、使用全局注册表共享Symbol值、遍历对象属性、使用Well-known Symbols自定义对象行为以及定义类的私有属性等。这些用法可以帮助我们更好地理解和应用Symbol。
Symbol属性
当使用内置的Symbol属性时,JavaScript引擎会根据这些属性的特定用途来执行相应的操作。下面是对每个示例的用法原理进行解释:
1. Symbol.iterator
- 当使用for…of循环遍历一个对象时,JavaScript引擎会查找该对象是否有一个Symbol.iterator方法。
- 如果存在Symbol.iterator方法,它应该返回一个迭代器对象,该迭代器对象包含next方法。
- 在每次迭代中,for…of循环会调用迭代器对象的next方法,并将返回的值赋给循环变量。
const obj = {
data: ['a', 'b', 'c'],
[Symbol.iterator]() {
let index = 0
return {
next: () => {
if (index < this.data.length) {
return { value: this.data[index++], done: false }
} else {
return { done: true }
}
}
}
}
}
for (let item of obj) {
console.log(item) // a, b, c
}
2. Symbol.toStringTag
- 当调用对象的toString()方法时,JavaScript引擎会检查该对象是否有一个Symbol.toStringTag属性。
- 如果存在Symbol.toStringTag属性,它应该是一个字符串值,表示自定义的字符串标签。
- JavaScript引擎将使用这个标签来构造toString()方法返回的字符串。
const obj = {
[Symbol.toStringTag]: 'MyObject',
};
console.log(obj.toString()); // [object MyObject]
3. Symbol.hasInstance:
- 当使用instanceof操作符检查一个实例是否属于某个类时,JavaScript引擎会查找这个类是否有一个静态方法[Symbol.hasInstance]。
- 如果存在[Symbol.hasInstance]方法,它应该接受一个参数,并返回一个布尔值表示实例是否属于这个类。
class MyClass {
static [Symbol.hasInstance](instance) {
return Array.isArray(instance)
}
}
console.log([] instanceof MyClass) // true
console.log({} instanceof MyClass) // false
4. Symbol.species:
- 当在派生类中调用Array原型上的方法(如map、filter等)创建新实例时,JavaScript引擎会查找派生类是否有一个静态属性[Symbol.species]。
- 如果存在[Symbol.species]属性,它应该是一个构造函数,用于创建新实例。
- JavaScript引擎将使用[Symbol.species]指定的构造函数来创建新实例,而不是使用派生类本身的构造函数。
class MyArray extends Array {
static get [Symbol.species]() {
return Array
}
}
const arr = new MyArray(1, 2, 3)
const newArr = arr.map((x) => x * 2)
console.log(newArr instanceof MyArray) // false
console.log(newArr instanceof Array) // true
5. Symbol.match、Symbol.replace、Symbol.search和Symbol.split:
- 当调用字符串的match、replace、search和split方法时,JavaScript引擎会查找传递给这些方法的参数是否有对应的Symbol属性。
- 如果存在对应的Symbol属性,它应该是一个方法,用于自定义字符串的匹配、替换、搜索和分割逻辑。
- JavaScript引擎将调用这些自定义方法来执行相应的操作。
class MyMatcher {
[Symbol.match](str) {
return str.includes('hello');
}
}
console.log('hello world'.match(new MyMatcher())); // true
总结
Symbol是ES6中引入的一种新的原始数据类型,用于创建唯一且不可变的标识符。它可以用作对象属性的键,解决属性名冲突的问题。Symbol还可以用于全局注册表、遍历对象属性和使用内置的Well-known Symbols等场景。
使用内置的Symbol属性时,JavaScript引擎会根据这些属性的特定用途来执行相应的操作。每个属性都有特定的行为规范,通过实现这些规范,我们可以自定义对象行为、扩展内置对象功能或实现特定功能。
😶 写在结尾
前端设计模式专栏
设计模式是软件开发中不可或缺的一部分,它们帮助我们解决了许多常见问题,并提供了一种优雅而可靠的方式来构建应用程序。在本专栏中,我们介绍了所有的前端设计模式,包括观察者模式、单例模式、策略模式等等。通过学习这些设计模式,并将其应用于实际项目中,我们可以提高代码的可维护性、可扩展性和可重用性。希望这个专栏能够帮助你在前端开发中更好地应用设计模式,写出高质量的代码。点击订阅前端设计模式专栏
Vue专栏
Vue.js是一款流行的JavaScript框架,用于构建用户界面。它采用了MVVM(Model-View-ViewModel)的架构模式,通过数据驱动和组件化的方式,使开发者能够更轻松地构建交互性强、可复用的Web应用程序。在这个专栏中,我们将深入探讨Vue.js的核心概念、组件开发、状态管理、路由和性能优化等方面的知识。我们将学习如何使用Vue.js构建响应式的用户界面,并探索其强大的生态系统,如Vue Router和Vuex、Pinia。通过学习这些内容,你将能够成为一名熟练的Vue.js开发者,并能够应用这些知识来构建复杂而高效的Web应用程序。点击订阅Vue专栏
JavaScript(ES6)专栏
JavaScript是一种广泛应用于网页开发和后端开发的脚本语言。它具有动态性、灵活性和易学性的特点,是构建现代Web应用程序的重要工具之一。在这个专栏中,我们将深入探讨JavaScript语言的基本语法、DOM操作、事件处理、异步编程以及常见算法和数据结构等内容。此外,我们还将介绍ES6(ECMAScript 2015)及其后续版本中引入的新特性,如箭头函数、模块化、解构赋值等。通过学习这些内容,你将能够成为一名熟练的JavaScript开发者,并能够应用这些知识来构建出高质量和可维护的Web应用程序。点击订阅JavaScript(ES6)专栏
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。 如若内容造成侵权/违法违规/事实不符,请联系我的编程经验分享网邮箱:veading@qq.com进行投诉反馈,一经查实,立即删除!