JavaScript编码之路【ES6新特性之 Symbol 、Set 、Map、迭代器、生成器】(一)

简介: JavaScript编码之路【ES6新特性之 Symbol 、Set 、Map、迭代器、生成器】(一)

前言

嘟三~ 嘟三~ 今日份广播题目:“怎么让JavaScript越来越6”。接下来,小菜鸡本人将和大家一起来探讨ES6-ES13的那些酷酷的新特性,从这次广播开始,你也可以炫耀:“这个ES新特性我都用得溜溜的!”

引子

ES6版本邀请了新的舞伴加入:Symbol、Set和Map,这三位舞伴各具特色,各自承担着不同的角色,使得JavaScript这个舞变得更加精彩。


一、Symbol

1.1. Symbol的基本使用

Symbol是什么呢?Symbol是ES6中新增的一个基本数据类型,翻译为符号。


那么为什么需要Symbol呢?


  • 在ES6之前,对象的属性名都是字符串形式,那么很容易造成属性名的冲突
  • 比如原来有一个对象,我们希望在其中添加一个新的属性和值,但是我们在不确定它原来内部有什么内容的情况下,很容易造成冲突,从而覆盖掉它内部的某个属性
  • 比如我们前面在讲apply、call、bind实现时,我们有给其中添加一个fn属性,那么如果它内部原来已经有了fn属性了呢?
  • 比如开发中我们使用混入【Mixin】,那么混入中出现了同名的属性,必然有一个会被覆盖掉

Symbol就是为了解决上面的问题,用来生成一个独一无二的值。

  • Symbol值是通过Symbol函数来生成的,生成后可以作为属性名
  • 也就是在ES6中,对象的属性名可以使用字符串,也可以使用Symbol
const s = Symbol()
console.log(s) // Symbol()

你无论怎么召唤他,他每次都会以一个全新的面孔出现

const s1 = Symbol()
const s2 = Symbol()

console.log(s1 === s2) // false

我们也可以在创建Symbol值的时候传入一个描述description【这个是ES2019(ES10)新增的特性】

const s3 = Symbol("abc")
console.log(s3.description)

1.2. Symbol作为属性名

Symbol的独特性使得他成为了一个好帮手。当你需要一个完全不会冲突的属性名时,你可以找到Symbol

写法一: 属性名赋值

const s1 = Symbol("abc")
const s2 = Symbol("cba")
const obj = {}
obj[s1] = "abc"
obj[s2] = "cba"

写法二: Object.defineProperty

const s1 = Symbol("abc")
const s2 = Symbol("cba")
const obj = {}
Object.defineProperty(obj, s1, {
  enumerable: true,
  configurable: true,
  writable: true,
  value: "abc"
})

写法三: 定义字面量是直接使用

const s1 = Symbol("abc")
const s2 = Symbol("cba")
const obj = {}
const info = {
  [s1]: "abc",
  [s2]: "cba"
}

之后我们可以通过Symbol值来获取值:

console.log(info[s1]) // abc
console.log(info[s2]) // cba
// 不能这样获取
console.log(info.s1) // undefined

但是通过Symbol添加的属性名,在遍历时,是无法获取到的:

console.log(Object.keys(info))
console.log(Object.getOwnPropertyNames(info))

如果我们希望获取Symbol的key,那么需要通过 Object.getOwnPropertyNames:

console.log(Object.getOwnPropertySymbols(info))
const symbolKeys = Object.getOwnPropertySymbols(info)
for (const key of symbolKeys) {
  console.log(info[key])
}

1.3. 相同值的Symbol

Symbol精灵的独特并不意味着他不能分享他的秘密。当你使用Symbol.for()召唤他的时候,他会首先翻阅他的记事本,看看你是不是之前就已经拜访过他,如果是的话,他就会带着他上次的面孔再次出现。

  • 我们可以使用Symbol.for方法来做到这一点
  • 并且我们可以通过Symbol.keyFor方法来获取对应的key
const s1 = Symbol.for("abc")
const s2 = Symbol.for("abc")

console.log(s1 === s2) // true
const key = Symbol.keyFor(s1)
console.log(key) // abc
const s3 = Symbol.for(key)
console.log(s2 === s3) // true


二. Set集合

在ES6之前,我们存储数据的结构主要有两种:数组、对象。

在ES6中新增了另外两种数据结构:Set、Map,以及它们的另外形式WeakSet、WeakMap。

2.1. Set的基本使用

Set是一个新增的数据结构,可以用来保存数据,类似于数组,但是和数组的区别是元素不能重复。你可以将Set想象成一个派对——在这个派对上,每个人都以其独特的个性和风格展现自我,没有人愿意模仿他人或被他人模仿。毕竟,你在派对上穿同样的衣服是多么尴尬的一件事情!


创建Set我们需要通过Set构造函数(暂时没有字面量创建的方式):

const set1 = new Set()
set1.add(10)
set1.add(14)
set1.add(16)
console.log(set1) // Set(3) { 10, 14, 16 }

const set2 = new Set([11, 15, 18, 11])
console.log(set2) // Set(3) { 11, 15, 18 }

我们可以发现Set中存放的元素是不会重复的,那么Set有一个非常常用的功能就是给数组去重。

const arr = [10, 20, 10, 44, 78, 44]
const set = new Set(arr)
const newArray1 = [...set]
const newArray2 = Array.from(set)
console.log(newArray1, newArray2)

2.2. Set的常见方法

Set常见的属性:

size:返回Set中元素的个数;

Set常用的方法:

add(value):添加某个元素,返回Set对象本身;

delete(value):从set中删除和这个值相等的元素,返回boolean类型;

has(value):判断set中是否存在某个元素,返回boolean类型;

clear():清空set中所有的元素,没有返回值;

forEach(callback, [, thisArg]):通过forEach遍历set;

set.add(100)
set.delete(100)
set.has(100)
set.clear()
set.forEach(item => {
  console.log(item)
})

另外Set是支持for of的遍历的:

for (const item of set) {
  console.log(item)
}

2.3. WeakSet使用

和Set类似的另外一个数据结构称之为WeakSet,也是内部元素不能重复的数据结构。

那么和Set有什么区别呢?

  • 区别一:WeakSet中只能存放对象类型,不能存放基本数据类型
  • 区别二:WeakSet对元素的引用是弱引用,如果没有其他引用对某个对象进行引用,那么GC可以对该对象进行回收
const wset = new WeakSet()

// TypeError: Invalid value used in weak set
wset.add(10)

WeakSet常见的方法:


  • add(value):添加某个元素,返回WeakSet对象本身;
  • delete(value):从WeakSet中删除和这个值相等的元素,返回boolean类型;
  • has(value):判断WeakSet中是否存在某个元素,返回boolean类型;

注意:WeakSet不能遍历

  • 因为WeakSet只是对对象的弱引用,如果我们遍历获取到其中的元素,那么有可能造成对象不能正常的销毁。
  • 所以存储到WeakSet中的对象是没办法获取的;

那么这个东西有什么用呢?

  • 事实上这个问题并不好回答,我们来使用一个Stack Overflow上的答案;

比如我们有一个类Person,里面有一个running方法,我们只希望你通过Person对象来调用:

class Person {
  running() {
    console.log("running", this)
  }
}

const p = new Person()
p.running()

p.running.call({name: "why"})

我们可以通过WeakSet来存储创建出来的对象,并且在调用方法时判断这个对象是否存在于WeakSet中:

const pwset = new WeakSet()
class Person {
  constructor() {
    pwset.add(this)
  }

  running() {
    if(!pwset.has(this)) throw new Error("不能通过其他对象调用running方法")
    console.log("running", this)
  }
}

const p = new Person()
p.running()

p.running.call({name: "why"})


.

JavaScript编码之路【ES6新特性之 Symbol 、Set 、Map、迭代器、生成器】(二):https://developer.aliyun.com/article/1556700

目录
相关文章
|
1月前
|
存储 Java 数据处理
Java Set接口凭借其独特的“不重复”特性,在集合框架中占据重要地位
【10月更文挑战第16天】Java Set接口凭借其独特的“不重复”特性,在集合框架中占据重要地位。本文通过快速去重和高效查找两个案例,展示了Set如何简化数据处理流程,提升代码效率。使用HashSet可轻松实现数据去重,而contains方法则提供了快速查找的功能,彰显了Set在处理大量数据时的优势。
33 2
|
1月前
|
存储 算法 Java
解析HashSet的工作原理,揭示Set如何利用哈希算法和equals()方法确保元素唯一性,并通过示例代码展示了其“无重复”特性的具体应用
在Java中,Set接口以其独特的“无重复”特性脱颖而出。本文通过解析HashSet的工作原理,揭示Set如何利用哈希算法和equals()方法确保元素唯一性,并通过示例代码展示了其“无重复”特性的具体应用。
41 3
|
1月前
|
存储 算法 Java
Java Set因其“无重复”特性在集合框架中独树一帜
【10月更文挑战第14天】Java Set因其“无重复”特性在集合框架中独树一帜。本文深入解析Set接口及其主要实现类(如HashSet、TreeSet)如何通过特定的数据结构(哈希表、红黑树)确保元素唯一性,并提供最佳实践建议,包括选择合适的Set实现类和正确实现自定义对象的`hashCode()`与`equals()`方法。
31 3
|
15天前
|
JavaScript 前端开发 Java
除了 JavaScript,还有哪些编程语言支持 Set 类型
【10月更文挑战第30天】这些编程语言中的 `Set` 类型虽然在语法和具体实现细节上有所不同,但都提供了类似的集合操作功能,方便开发者在不同的编程场景中处理集合相关的数据和逻辑。
|
1月前
|
Java 开发者
在Java的集合世界里,Set以其独特的特性脱颖而出,它通过“哈希魔法”和“红黑树防御”两大绝技
【10月更文挑战第13天】在Java的集合世界里,Set以其独特的特性脱颖而出。它通过“哈希魔法”和“红黑树防御”两大绝技,有效抵御重复元素的侵扰,确保集合的纯洁性和有序性。无论是“人海战术”还是“偷梁换柱”,Set都能从容应对,成为开发者手中不可或缺的利器。
31 6
|
1月前
|
Java 开发者
在Java集合世界中,Set以其独特的特性脱颖而出,专门应对重复元素
在Java集合世界中,Set以其独特的特性脱颖而出,专门应对重复元素。通过哈希表和红黑树两种模式,Set能够高效地识别并拒绝重复元素的入侵,确保集合的纯净。无论是HashSet还是TreeSet,都能在不同的场景下发挥出色的表现,成为开发者手中的利器。
27 2
|
1月前
|
Java
Java Set以其“不重复”的特性,为我们提供了一个高效、简洁的处理唯一性约束数据的方式。
【10月更文挑战第16天】在Java编程中,Set接口确保集合中没有重复元素,每个元素都是独一无二的。HashSet基于哈希表实现,提供高效的添加、删除和查找操作;TreeSet则基于红黑树实现,不仅去重还能自动排序。通过这两个实现类,我们可以轻松处理需要唯一性约束的数据,提升代码质量和效率。
36 2
|
1月前
|
存储 Java 数据处理
在Java集合框架中,Set接口以其独特的“不重复”特性脱颖而出
【10月更文挑战第14天】在Java集合框架中,Set接口以其独特的“不重复”特性脱颖而出。本文通过两个案例展示了Set的实用性和高效性:快速去重和高效查找。通过将列表转换为HashSet,可以轻松实现去重;而Set的contains方法则提供了快速的元素查找功能。这些特性使Set成为处理大量数据时的利器。
16 4
|
1月前
|
存储 Java 数据处理
Java中的Set接口以其独特的“不重复”特性,在集合框架中占据重要地位。
【10月更文挑战第13天】Java中的Set接口以其独特的“不重复”特性,在集合框架中占据重要地位。本文通过两个案例展示了Set的实用性和高效性:快速去重和高效查找。通过将列表转换为HashSet,可以轻松实现去重;而Set的contains方法则提供了高效的元素查找功能。这些特性使Set在处理大量数据时表现出色,值得我们在日常编程中充分利用。
33 3
|
1月前
|
存储 JavaScript 前端开发
Set、Map、WeakSet 和 WeakMap 的区别
在 JavaScript 中,Set 和 Map 用于存储唯一值和键值对,支持多种操作方法,如添加、删除和检查元素。WeakSet 和 WeakMap 则存储弱引用的对象,有助于防止内存泄漏,适合特定场景使用。
下一篇
无影云桌面