ES6新特性-06
第十六章:新的数据类型和特性
JavaScript在ES6中引入了一些新的数据类型和特性,用来丰富语言的功能和提高开发人员的效率。本章将介绍几种新的数据类型和特性,包括Set和Map、Symbol和WeakSet、以及Reflect和Proxy。
1.Set 和 Map
Set
和Map
这两种新数据类型分别用于存储集合和键值对,提供了更灵活的数据存储方式。如果常做算法的小伙伴肯定是对它们记得是滚瓜烂熟了,因为我们经常能够碰到哈希表的题目,以及一些需要用到集合去重的题目。
但是我还是要向不太了解它们的小伙伴们介绍一下它们,我也会附上一个简单的力扣题目案例,来让大家尝试使用它们~
Set:
首先是Set
,Set
是一种集合数据结构,它的主要特点是就是存储唯一的值,不允许重复,哪怕我们给它一个包含重复值的数组,它也会贴心的帮我们删掉。所以我们一般可以将Set
对象用于去重数组中的元素或存储唯一的标识符。以下是Set的基本用法:
const uniqueNumbers = new Set([1, 2, 2, 3, 3, 3]);
console.log(uniqueNumbers); // 输出 Set { 1, 2, 3 }
在上面的示例中,Set
对象uniqueNumbers
存储了一组数字,但重复的数字被自动去重,最终只保留了唯一的值。
来一套力扣热热身:
26. 删除有序数组中的重复项: 给你一个 非严格递增排列 的数组 nums
,请你 原地 删除重复出现的元素,使每个元素 只出现一次 ,返回删除后数组的新长度。元素的 相对顺序 应该保持 一致 。然后返回 nums
中唯一元素的个数。
考虑 nums
的唯一元素的数量为 k
,你需要做以下事情确保你的题解可以被通过:
- 更改数组
nums
,使nums
的前k
个元素包含唯一元素,并按照它们最初在nums
中出现的顺序排列。nums
的其余元素与nums
的大小不重要。 - 返回
k
。
你来想一想我们可以怎么样利用set
的这个特性来实现,当你想到删除``重复
两个关键词的时候,我们就可以想到使用Set
,我们直接把数组传进去不就去重了吗?我们来试试:
var removeDuplicates = function(nums)
// 创建一个空的Set,用于存储不重复的元素
const set = new Set(nums);
// 将Set中的元素转换为数组
const uniqueArray = Array.from(set);
// 将数组复制回原数组nums,使得nums中的元素就是不重复的元素
for (let i = 0; i < uniqueArray.length; i++) {
nums[i] = uniqueArray[i];
}
// 返回不重复元素的个数,即新数组的长度
return uniqueArray.length;
};
没问题,直接通过~ 但是这里有一个小问题哦,我们这个其实不是原地算法,只能算取巧地通过了,这就体现出JavaScript的偷鸡
属性了,咳咳,提供了更灵活的数据存储方式~
Map:
Map是一种键值对的数据结构,它可以存储各种类型的值作为键,并且可以非常高效地进行增加、查找和删除操作。Map对象可以用于存储配置信息、缓存数据等。map在算法里那可就有更多了,因为其实这种储存方式就是哈希表,凡是哈希表的题都可以解~
先看看Map的基本用法:
const config = new Map();
config.set('language', 'JavaScript');
config.set('version', 'ES6');
if(config.has(language)){
console.log(config.get('language')); // 输出 'JavaScript'
}
Map对象config
存储了一组键值对,我们可以使用set
方法添加键值对,s使用has来查找是否存在,使用get
方法查找对应键的值。
再来一套力扣热热身:
442. 数组中重复的数据:给你一个长度为 n
的整数数组 nums
,其中 nums
的所有整数都在范围 [1, n]
内,且每个整数出现 一次 或 两次 。请你找出所有出现 两次 的整数,并以数组形式返回。
你必须设计并实现一个时间复杂度为 O(n)
且仅使用常量额外空间的算法解决此问题。
示例 1:
ini复制代码输入: nums = [4,3,2,7,8,2,3,1]
输出: [2,3]
当你看到这道题,哟?这不是重复嘛,几行不见又是你?这回我们只看见了重复,诶?那我们直接用map储存值和出现次数不就可以了嘛?我们来试试:
var findDuplicates = function(nums) {
let map = new Map()
let ans = []
for(let i = 0 ;i < nums.length; i++){
if(map.has(nums[i])){ // map中存在nums[i]的话说明重复了
ans.push(nums[i]) // 从尾部插入到答案数组
}else{
map.set(nums[i], 1) // 不存在的话新建一个
}
}
return ans
};
没问题,直接通过~ 这还是一道中等题呢,满打满算十行结束,JavaScript的数据结构就是有这么爽~
2.Symbol 和 WeakSet
Symbol 和 WeakSet
是两个不同的 JavaScript 特性,它们也是ES6新增的两个特性,它们在解决问题时有着不同的作用,让我们一起来看看吧~
Symbol
Symbol是一种原始数据类型,用于创建唯一的、不可变的值。它通常用于定义对象属性名,以避免属性名冲突或用于元编程的场景。Symbol
的特性使它在某些特定问题上还是非常有用的。这里是一个使用Symbol
的示例:
const uniqueKey = Symbol('uniqueKey');
const obj = {};
obj[uniqueKey] = 'This is a unique property';
console.log(obj[uniqueKey]); // 输出 'This is a unique property'
在上面的示例中,我们创建了一个唯一的Symbol,将其用作对象的属性名,从而确保属性名的唯一性。
应用
- 防止属性名冲突:在一些复杂的数据结构或多人协作的项目中,使用Symbol作为属性名可以避免属性名冲突。由于Symbol的唯一性,它可以用来定义私有属性或特殊用途的属性,而不会与其他属性发生冲突。
const uniqueKey = Symbol('uniqueKey');
const obj = {
[uniqueKey]: 'This is a unique property'
};
console.log(obj[uniqueKey]); // 输出 'This is a unique property'
- 定义常量:可以使用Symbol来定义不容易被覆盖的常量值。
const RED = Symbol('red');
const GREEN = Symbol('green');
const BLUE = Symbol('blue');
- 元编程:Symbol允许进行元编程,即编写能够操作或定义其他代码的代码。例如,可以使用Symbol来定义自定义迭代器。
const iterable = {
[Symbol.iterator]: function* () {
yield 1;
yield 2;
yield 3;
}
};
for (const value of iterable) {
console.log(value); // 输出 1, 2, 3
}
WeakSet
WeakSet是一种特殊类型的Set,它只能存储对象,并且不会阻止这些对象被垃圾回收。WeakSet通常用于存储对象的弱引用,以确保对象在不再需要时可以被自动清理,从而避免内存泄漏。以下是一个使用WeakSet的示例:
javascript复制代码const myWeakSet = new WeakSet();
const obj1 = {};
const obj2 = {};
myWeakSet.add(obj1);
myWeakSet.add(obj2);
console.log(myWeakSet.has(obj1)); // 输出 true
// 垃圾回收后,obj2将自动从WeakSet中移除
WeakSet用于存储对象的弱引用,这意味着如果对象不再被引用,它将被垃圾回收,并且从WeakSet中自动移除。
应用
- 管理对象引用:WeakSet通常用于管理对象的引用,特别是在需要确保对象在不再被引用时可以被垃圾回收的情况下。这可以避免内存泄漏,这个可以看看这篇文章:原来闭包可以这么简单这里面就讲到了闭包产生的内存泄漏。
const myWeakSet = new WeakSet();
const obj1 = {};
const obj2 = {};
myWeakSet.add(obj1);
myWeakSet.add(obj2);
console.log(myWeakSet.has(obj1)); // 输出 true
// 垃圾回收后,obj2将自动从WeakSet中移除
- 弱引用缓存:WeakSet可以用于实现缓存,其中对象可以被垃圾回收,从而节省内存。
const cache = new WeakSet();
function getCachedData(data) {
if (cache.has(data)) {
return data;
} else {
cache.add(data);
return data;
}
}
不过和Set和Map不太一样,在LeetCode上,使用Symbol和WeakSet来解决问题相对较少,因为它们一般都在在更高水平的编程任务中使用。比如说Symbol
可能用于一些高级数据结构的实现,而WeakSet
通常用于管理对象的生命周期。