跳至主要內容

ES6新特性-06

Heyn大约 7 分钟ES6Javascript

第十六章:新的数据类型和特性

JavaScript在ES6中引入了一些新的数据类型和特性,用来丰富语言的功能和提高开发人员的效率。本章将介绍几种新的数据类型和特性,包括Set和Map、Symbol和WeakSet、以及Reflect和Proxy。

1.Set 和 Map

SetMap这两种新数据类型分别用于存储集合和键值对,提供了更灵活的数据存储方式。如果常做算法的小伙伴肯定是对它们记得是滚瓜烂熟了,因为我们经常能够碰到哈希表的题目,以及一些需要用到集合去重的题目。

但是我还是要向不太了解它们的小伙伴们介绍一下它们,我也会附上一个简单的力扣题目案例,来让大家尝试使用它们~

Set:

首先是SetSet是一种集合数据结构,它的主要特点是就是存储唯一的值,不允许重复,哪怕我们给它一个包含重复值的数组,它也会贴心的帮我们删掉。所以我们一般可以将Set对象用于去重数组中的元素或存储唯一的标识符。以下是Set的基本用法:

const uniqueNumbers = new Set([1, 2, 2, 3, 3, 3]);
console.log(uniqueNumbers); // 输出 Set { 1, 2, 3 }

在上面的示例中,Set对象uniqueNumbers存储了一组数字,但重复的数字被自动去重,最终只保留了唯一的值。

来一套力扣热热身:

26. 删除有序数组中的重复项open in new window: 给你一个 非严格递增排列 的数组 nums ,请你 原地open in new window 删除重复出现的元素,使每个元素 只出现一次 ,返回删除后数组的新长度。元素的 相对顺序 应该保持 一致 。然后返回 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. 数组中重复的数据open in new window:给你一个长度为 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,将其用作对象的属性名,从而确保属性名的唯一性。

应用

  1. 防止属性名冲突:在一些复杂的数据结构或多人协作的项目中,使用Symbol作为属性名可以避免属性名冲突。由于Symbol的唯一性,它可以用来定义私有属性或特殊用途的属性,而不会与其他属性发生冲突。
const uniqueKey = Symbol('uniqueKey');

const obj = {
  [uniqueKey]: 'This is a unique property'
};

console.log(obj[uniqueKey]); // 输出 'This is a unique property'
  1. 定义常量:可以使用Symbol来定义不容易被覆盖的常量值。
const RED = Symbol('red');
const GREEN = Symbol('green');
const BLUE = Symbol('blue');
  1. 元编程: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中自动移除。

应用

  1. 管理对象引用:WeakSet通常用于管理对象的引用,特别是在需要确保对象在不再被引用时可以被垃圾回收的情况下。这可以避免内存泄漏,这个可以看看这篇文章:原来闭包可以这么简单open in new window这里面就讲到了闭包产生的内存泄漏。
const myWeakSet = new WeakSet();

const obj1 = {};
const obj2 = {};

myWeakSet.add(obj1);
myWeakSet.add(obj2);

console.log(myWeakSet.has(obj1)); // 输出 true

// 垃圾回收后,obj2将自动从WeakSet中移除
  1. 弱引用缓存: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通常用于管理对象的生命周期。

上次编辑于:
贡献者: HeynXi