摘要:中模拟与长久以来,数组一直是中唯一的集合类型。用数组初始化集合事实上,只要是可迭代对象数组集合集合,都可以作为构造函数的参数。构造函数通过迭代器从参数中提取值。
ES5中模拟Set与Map
长久以来,数组一直是JavaScript中唯一的集合类型。如果开发者们需要使用非数值型索引,就会用非数组对象创建所需的数据结构,而这就是Set集合与Map集合的早期实现。
一般来说,Set集合常被用于检查对象中是否存在某个键名,而Map集合常被用于获取已存在的信息。
ES5模拟的Set集合var set = Object.create(null); set.foo = true; // 检查属性是否存在 if(set.foo) { // 要执行的代码 }
ES5中,开发者们经常用类似的方法检查对象的某个属性是否存在。
ES5模拟的Map集合var map = Object.create(null); map.foo = "bar"; // 获取已存值 var value = map.foo; console.log(value); // "bar"
模拟这两种集合对象的唯一区别是存储的值不同。
ES5模拟解决方案的问题一般情况下,确实可以用对象来模拟Set集合与Map集合,但如果触碰到对象属性的某些限制,情况会变得复杂。请看这段代码:
var map = Object.create(null); map[5] = "foo"; console.log(map["5"]); // "foo"
由于对象属性名必须是字符串类型,示例中数值型的map[5],会被自动转换成字符串map["5"]。如果你想分别用数字和字符串作为对象属性的键名,则内部的自动转换机制会导致许多问题。
再看下面这个示例:
var map = Object.create(null), key1 = {}, key2 = {}; map[key1] = "foo"; console.log(map[key2]); // "foo"
同样,由于对象属性名必须是字符串,代码中的map[key1]和map[key2]都将被转换成map["[object object]"]。这种错误很难被发现。
对于Map集合来说,如果它的属性值是假值,则在要求使用布尔值的情况下(例如在if语句中)会被自动转换为false。强制转换本身没有问题,但如果考虑这个值的使用场景,就有可能发生问题。例如:
var map = Object.create(null); map.count = 1; // 本意是检查"count"属性是否存在,实际上检查的是该值是否非零 if (map.count) { // 要执行的代码 }
这个示例有些模棱两可的地方。在if语句中,我们是检查map.count是否存在,还是检查值是否非零?由于value的值是1,为真值,if语句中的代码将被执行。然而,如果map.count的值为0或者不存在,if语句中的代码将不被执行。
大型应用中,一旦发生此类问题将难以定位和调试,促使ES6加入Set与Map集合两种新特性。
ES6中的Set集合ES6新增的Set是一种集合类型的数据结构,承载着有序不可重复的值。
Set集合的相关操作new Set()构造函数:创建Set集合
add()方法:往集合添加元素
size属性:集合长度
has()方法:判断集合内是否包含某元素
delete()方法:从集合中删除某元素
clear()方法:清空集合元素
forEach()方法:遍历集合元素
相关操作示例:
let set = new Set(); set.add("5"); set.add(5); // 不会强制类型转换,数字5和字符串"5"可以作为两个独立元素存在 set.add(5); // 重复 - 本次调用直接被忽略 console.log(set.has(5)); // true console.log(set.has("5")); // true console.log(set.has(6)); // false console.log(set.size); // 2 set.delete(5); console.log(set.has(5)); // false console.log(set.has("5")); // true console.log(set.size); // 1 set.clear(); console.log(set.has("5")); // false console.log(set.size); // 0
如果向Set集合添加多个对象,它们之间也是彼此独立的:
let set = new Set(); key1 = {}, key2 = {}; set.add(key1); set.add(key2); console.log(set.size); // 2
由于key1和key2不会被转换成字符串,因而它们在Set集合中是两个独立元素。
用数组初始化Set集合let set = new Set([1, 2, 3, 4, 5, 5, 5, 5]); console.log(set.size); // 5
事实上,只要是可迭代对象(数组、Set集合、Map集合),都可以作为Set构造函数的参数。构造函数通过迭代器从参数中提取值。
Set集合的forEach方法Set集合的forEach方法与Map集合和数组中的forEach()方法类似,回调函数都接受3个参数:
Set集合当前遍历元素的值
Set集合当前遍历元素的键(Set集合键与值相同;数组是索引值)
Set集合本身
let set = new Set([1, 2]); set.forEach(function(value, key, ownerSet) { console.log(key + " " + value); console.log(ownerSet === set); });
以上示例输出的内容:
1 1 true 2 2 true
如果需要在回调函数中使用this引用,则可以将它作为第二个参数传入forEach()函数:
let set = new Set([1, 2]); let processor = { output(value) { console.log(value); }, process(dataSet) { dataSet.forEach(function(value)) { this.output(value); // 从而正确调用到processor.output()方法 }, this); } }; processor.process(set);
当然,你可以使用箭头函数,这样就无需再讲this作为第二个参数传入了:
let set = new Set([1, 2]); let processor = { output(value) { console.log(value); }, process(dataSet) { dataSet.forEach(value => this.output(value)); } }; processor.process(set);将Set集合转换为数组
尽管Set集合适合用来跟踪多个值,而且又可以通过forEach()方法操作集合中的每一个元素,但是你不能像访问数组元素那样直接通过索引访问集合中的元素。如有需要,先将Set集合转换成一个数组。
展开运算符可以很方便地将诸如Set集合的可迭代对象转换为数组:
let set = new Set([1, 2, 3, 3, 3, 4, 5]), array = [...set]; console.log(array); // [1,2,3,4,5]
如果已经创建过一个数组,想要复制它并创建一个无重复元素的新数组,则上述这个方法十分管用,请看:
function eliminateDuplicates(items) { return [...new Set(items)]; } let numbers = [1, 2, 3, 3, 3, 4, 5], noDuplicates = eliminateDuplicates(numbers); console.log(noDuplicates); // [1,2,3,4,5]ES6中的Map集合
ES6中的Map类型是一种存储着许多键值对的有序列表,其中的键名和对应的值支持所有的数据类型。
Map集合的相关操作new Map()构造函数:创建Map集合
set()方法:往集合中添加新元素[键值对]
size属性:集合元素个数
get()方法:从集合中获取某个键对应的值
has()方法:判断集合中是否存在某键的元素
delete()方法:从集合中删除某键的元素
clear()方法:清空集合元素
forEach()方法:遍历集合元素
相关操作示例:
let map = new Map(); map.set("name", "Nicholas"); map.set("age", 25); console.log(map.size); // 2 console.log(map.has("name")); // true console.log(map.get("name")); // "Nicholas" console.log(map.has("age")); // true console.log(map.get("age")); // 25 map.delete("name"); console.log(map.has("name")); // false console.log(map.get("name")); // undefined console.log(map.size); // 1 map.clear(); console.log(map.has("name")); // false console.log(map.get("name")); // undefined console.log(map.has("age")); // false console.log(map.get("age")); // undefined console.log(map.size); // 0用数组初始化Map集合
let map = new Map([["name", "Nicholas"], ["age", 25]]); console.log(map.has("name")); // true console.log(map.get("name")); // "Nicholas" console.log(map.has("age")); // true console.log(map.get("age")); // 25 console.log(map.size); // 2Map集合的forEach方法
Map集合的forEach方法与Set集合和数组中的forEach()方法类似,回调函数都接受3个参数:
Map集合当前遍历元素的值
Map集合当前遍历元素的键
Map集合本身
let map = new Map([["name", "Nicholas"], ["age", 25]]); map.forEach(function(value, key, ownerMap) { console.log(key + " " + value); console.log(ownerMap === map); });
会按照键值对插入Map集合顺序遍历,输出内容:
name Nicholas true age 25 true
文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。
转载请注明本文地址:https://www.ucloud.cn/yun/85105.html
摘要:前言新增了两种基本的原生数据集合和加上和现在共有四种,以及由两者衍生出的弱引用集合和。其本身是生成实例数据集合的构造函数,可以接受一个数组或具有接口的数据结构作为参数用来初始化。返回键值对的遍历器对象,键值对为键名键值。 前言 ES6新增了两种基本的原生数据集合:Set和Map(加上Array和Object现在共有四种),以及由两者衍生出的弱引用集合:WeakSet和WeakMap。从...
摘要:由于和不会被转换为字符串,所以在内部是不同的项,如果他们被转化为字符串,那么都会等于,如果多次调用并传入相同的值作为参数。第二次重复传入并不会被添加到集合中,那么的属性值还是为。的方法和共享了几个方法。小结正式将与引入。 se5中的set与map 在est5中开发者使用对象属性来模拟。set多用于检查键的存在,map多用于提取数据。 { let set = Object.cre...
摘要:常被用来检查对象中是否存在某个键名,集合常被用来获取已存的信息。返回一个布尔值,表示该值在中存在与否。集合存放对象的弱引用,当该对象的其他强引用被清除时,集合中的弱引用也会自动被垃圾回收机制回收,追踪成组的对象是该集合最好的使用方式。 Map和Set都叫做集合,但是他们也有所不同。Set常被用来检查对象中是否存在某个键名,Map集合常被用来获取已存的信息。 Set Set是有序列表,含...
阅读 3732·2021-09-22 15:17
阅读 1925·2021-09-22 14:59
阅读 2309·2020-12-03 17:00
阅读 3183·2019-08-30 15:55
阅读 464·2019-08-30 11:23
阅读 3454·2019-08-29 13:56
阅读 482·2019-08-29 12:54
阅读 2206·2019-08-29 12:49