[ES6] Set、Map
#
Map
new Map([iterable])
返回一个新的Map对象。
如果参数iterable是一个数组或者其他可迭代的对象--它的元素是键值对,
这样这些的每一个键值对都可以添加到新的Map里面去
Map对象就是简单的键/值映射.其中键和值可以是任意值(原始值或对象值).
在判断两个值是否为同一个键的时候,使用的并不是===运算符,而是使用了一种称之为"same-value"的内部算法,
该算法很特殊, 对于Map对象来说, +0 (按照以往的经验与 -0 是严格相等的)和-0 是两个不同的键.
而NaN在作为Map对象的键时和另外一个NaN是一个相同的键(尽管NaN !== NaN).
Object和Map的比较
Object和Map类似的一点是,它们都允许你按键存取一个值,都可以删除键,还可以检测一个键是否绑定了值.
因此,一直以来,我们都把对象当成Map来使用,不过,现在有了Map,下面的区别解释了为什么使用Map更好点:
一个对象通常都有自己的原型,所以一个对象总有一个"prototype"键.不过,现在可以使用map = Object.create(null)来创建一个没有原型的对象.
一个对象的键只能是字符串,但一个Map的键可以是任意值.
可以很容易的得到一个Map的键值对个数,而只能跟踪一个对象的键值对个数
Map.prototype.size
Map.prototype.clear()
Map.prototype.delete(key)
Map.prototype.entries()
Map.prototype.forEach(callbackFn[, thisArg])
Map.prototype.get(key)
Map.prototype.has(key)
Map.prototype.keys()
Map.prototype.set(key, value)
Map.prototype.values()
Map.prototype[@@iterator]()
#Using the Map object
var myMap = new Map();
var keyObj = {},
keyFunc = function() {},
keyString = "a string";
// 添加键
myMap.set(keyString, "和键'a string'关联的值");
myMap.set(keyObj, "和键keyObj关联的值");
myMap.set(keyFunc, "和键keyFunc关联的值");
console.log(myMap.size); // 3
// 读取值
console.log(myMap.get(keyString)); // "和键'a string'关联的值"
console.log(myMap.get(keyObj)); // "和键keyObj关联的值"
console.log(myMap.get(keyFunc)); // "和键keyFunc关联的值"
console.log(myMap.get("a string")); // "和键'a string'关联的值"
// 因为keyString === 'a string'
console.log(myMap.get({})); // undefined, 因为keyObj !== {}
console.log(myMap.get(function() {})); // undefined, 因为keyFunc !== function () {}
NaN 也可以作为Map对象的键. 虽然 NaN 和任何值甚至和自己都不相等(NaN !== NaN 返回true),
#两个NaN作为Map的键来说是没有区别的
var myMap = new Map();
myMap.set(NaN, "not a number");
console.log(myMap.get(NaN)); // "not a number"
var otherNaN = Number("foo");
console.log(myMap.get(otherNaN)); // "not a number"
#Iterating Maps with for..of
Maps can be iterated using a for..of loop:
var myMap = new Map();
myMap.set(0, "zero");
myMap.set(1, "one");
for (var [key, value] of myMap) {
console.log(key + " = " + value);
}
//0 = zero
//1 = one
// Will show 2 logs; first with "0 = zero" and second with "1 = one"
for (var key of myMap.keys()) {
console.log(key);
}
// Will show 2 logs; first with "0" and second with "1"
for (var value of myMap.values()) {
console.log(value);
}
// Will show 2 logs; first with "zero" and second with "one"
for (var [key, value] of myMap.entries()) {
console.log(key + " = " + value);
}
// Will show 2 logs; first with "0 = zero" and second with "1 = one"
#Iterating Maps with forEach()
Maps can be iterated using the forEach() method
var myMap = new Map(); myMap.set(0, "zero"); myMap.set(1, "one"); myMap.forEach(function(value, key) { console.log(key + " = " + value); }, myMap) // Will show 2 logs; first with "0 = zero" and second with "1 = one"
Map.prototype.size
size 可访问属性返回 Map 对象的元素数量.
size 属性的值是一个整数,表示 Map 对象有多少个键值对。
size 是只读属性,它对应的 set 方法是 undefined,即不能改变它的值。
#
var myMap = new Map(); myMap.set("a", "alpha"); myMap.set("b", "beta"); myMap.set("g", "gamma"); console.log(myMap.size); // 3
Map.prototype[@@toStringTag]
Map[Symbol.toStringTag]
The Map[@@toStringTag] property has an initial value of "Map".
#
Object.prototype.toString.call(new Map()) // "[object Map]"
Map.prototype.set()
myMap.set(key, value);
The set() method adds a new element with a specified key and value to a Map object.
#
var myMap = new Map(); // Add new elements to the map myMap.set("bar", "foo"); console.log(myMap.get("bar")); // "foo" myMap.set(1, "foobar"); // Update an element in the map myMap.set("bar", "baz"); console.log(myMap.get("bar")); // "baz" console.log(myMap.get(1)); // "foobar"
Map.prototype.get()
myMap.get(key);
get() 方法用来获取一个 Map对象中指定的元素。
#
var myMap = new Map(); myMap.set("bar", "foo"); console.log(myMap.get("bar")); // "foo" console.log(myMap.get("baz")); // undefined
Map.prototype.values()
myMap.values()
The values() method returns a new Iterator object that contains the values for each element in the Map object in insertion order.
#
var myMap = new Map(); myMap.set("0", "foo"); myMap.set(1, "bar"); myMap.set({}, "baz"); var mapIter = myMap.values(); console.log(mapIter.next().value); // "foo" console.log(mapIter.next().value); // "bar" console.log(mapIter.next().value); // "baz"
Map.prototype.keys()
myMap.keys()
The keys() method returns a new Iterator object that contains the keys for each element in the Map object in insertion order.
#
var myMap = new Map(); myMap.set("0", "foo"); myMap.set(1, "bar"); myMap.set({}, "baz"); var mapIter = myMap.keys(); console.log(mapIter.next().value); // "0" console.log(mapIter.next().value); // 1 console.log(mapIter.next().value); // Object {}
Map.prototype.entries()
myMap.entries()
The entries() method returns a new Iterator object that contains the [key, value] pairs for each element in the Map object in insertion order.
#
var myMap = new Map(); myMap.set("0", "foo"); myMap.set(1, "bar"); myMap.set({}, "baz"); var mapIter = myMap.entries(); console.log(mapIter.next().value); // ["0", "foo"] console.log(mapIter.next().value); // [1, "bar"] console.log(mapIter.next().value); // [Object, "baz"]
Map.prototype[@@iterator]()
myMap[Symbol.iterator]
The initial value of the @@iterator property is the same function object as the initial value of the entries property.
#[Symbol.iterator]
var myMap = new Map(); myMap.set("0", "foo"); myMap.set(1, "bar"); myMap.set({}, "baz"); var mapIter = myMap[Symbol.iterator](); console.log(mapIter.next().value); // ["0", "foo"] console.log(mapIter.next().value); // [1, "bar"] console.log(mapIter.next().value); // [Object, "baz"]
#Using [@@iterator]() with for..of
var myMap = new Map(); myMap.set("0", "foo"); myMap.set(1, "bar"); myMap.set({}, "baz"); for (var v of myMap) { console.log(v); } // ["0", "foo"] // [1, "bar"] // [Object, "baz"]
Map.prototype.has()
myMap.has(key);
方法has() 返回一个bool值,用来表明map 中是否存在指定元素.
#
var myMap = new Map(); myMap.set("bar", "foo"); console.log(myMap.has("bar")); // returns true console.log(myMap.has("baz")); // returns false
Map.prototype.delete()
delete()删除Map实例key指定的值。
#
var myMap = new Map(); myMap.set("bar", "foo"); console.log(myMap.get("bar"));//"foo" console.log(myMap.delete("bar")); // Returns true. Successfully removed. console.log(myMap.has("bar")); // Returns false. The "bar" element is no longer present.
Map.prototype.clear()
myMap.clear();
clear()方法会移除Map对象中的所有元素。
#
var myMap = new Map(); myMap.set("bar", "baz"); console.log(myMap.set(1, "foo"));//Map {"bar" => "baz", 1 => "foo"} console.log(myMap);//Map {"bar" => "baz", 1 => "foo"} console.log(myMap.size); // 2 console.log(myMap.has("bar")); // true myMap.clear(); console.log(myMap.size); // 0 console.log(myMap.has("bar")); // false
Map.prototype.forEach()
myMap.forEach(callback[, thisArg])
将会以插入顺序对 Map 对象中的每一个键值对执行一次参数中提供的回调函数。
#
function logMapElements(value, key, map) { console.log("m[" + key + "] = " + value); } new Map([ ["foo", 3], ["bar", {}], ["baz", undefined] ]).forEach(logMapElements); // logs: // "m[foo] = 3" // "m[bar] = [object Object]" // "m[baz] = undefined"
WeakMap
WeakMap.prototype.delete(key)
WeakMap.prototype.get(key)
WeakMap.prototype.has(key)
WeakMap.prototype.set(key, value)
WeakMap对象就是简单的键/值映射.但键只能是对象值,不可以是原始值.
弱引用, WeakMap 的keys无法遍历
#
var wm1 = new WeakMap(), wm2 = new WeakMap(), wm3 = new WeakMap(); var o1 = {}, o2 = function(){}, o3 = window; console.log(wm1.set(o1, 37)); console.log(wm1.set(o2, "azerty")); console.log(wm2.set(o1, o2)); // value可以是任意值,包括一个对象 console.log(wm2.set(o3, undefined)); console.log(wm2.set(wm1, wm2)); // 键和值可以是任意对象,甚至另外一个WeakMap对象 console.log(wm1.get(o2)); // "azerty" console.log(wm2.get(o2)); // undefined,wm2中没有o2这个键 console.log(wm2.get(o3)); // undefined,值就是undefined console.log(wm1.has(o2)); // true console.log(wm2.has(o2)); // false console.log(wm2.has(o3)); // true (即使值是undefined) console.log(wm3.set(o1, 37)); console.log(wm3.get(o1)); // 37 console.log(wm1.has(o1)); // true console.log(wm1.delete(o1)); console.log(wm1.has(o1)); // false
Set
new Set([iterable]);
集合(Set)对象允许你存储任意类型的唯一值(不能重复),无论是primitive values还是对象引用。
Set对象是值的集合,你可以按照插入的顺序迭代它的元素。
Set中的元素只会出现一次,即 Set 中的元素是唯一的。
因为Set中的值总是唯一的,所以需要判断两个值是否相等。
Set.prototype.size
Set.prototype.add(value)
Set.prototype.clear()
Set.prototype.delete(value)
Set.prototype.entries()
Set.prototype.forEach(callbackFn[, thisArg])
Set.prototype.has(value)
Set.prototype.keys()
Set.prototype.values()
Set.prototype[@@iterator]()
#
var mySet = new Set(); mySet.add(1); mySet.add(5); mySet.add("some text"); console.log(mySet);//Set {1, 5, "some text"} console.log(mySet.has(1)); // true console.log(mySet.has(3)); // false, 3没有被添加到set中 console.log(mySet.has(5)); // true console.log(mySet.has(Math.sqrt(25))); // true console.log(mySet.has("Some Text".toLowerCase())); // true console.log(mySet.size); // 3 mySet.delete(5); // 从set中移除5 console.log(mySet.has(5)); // false, 5已经被移除 console.log(mySet.size); // 2, 我们刚刚移除了一个值
#迭代Set
var mySet = new Set(); mySet.add(1); mySet.add("some text"); // 迭代整个set // 按顺序输出:1, "some text" for (let item of mySet) console.log(item); // 按顺序输出:1, "some text" for (let item of mySet.keys()) console.log(item); // 按顺序输出:1, "some text" for (let item of mySet.values()) console.log(item); // 按顺序输出:1, "some text" //(键与值相等) for (let [key, value] of mySet.entries()) console.log(key); // 转换Set为Array (with Array comprehensions) //var myArr = [v for (v of mySet) ]; // false [1, "some text"] // 替代方案(with Array.from) var myArr = Array.from(mySet); // false [1, "some text"] console.log(myArr);// [1, "some text"] // 如果在HTML文档中工作,也可以: mySet.add(document.body); mySet.has(document.querySelector("body")); // true // Set和Array互换 mySet2 = new Set([1, 2, 3, 4]); console.log(mySet2.size); // 4 [...mySet2]; // [1,2,3,4] // 截取 //var intersection = new Set([x for (x of set1) if (set2.has(x)) ]); // 用forEach迭代 mySet2.forEach(function(value) { console.log(value); }); // 1 // 2 // 3 // 4
#和Array对象的关系
var myArray = ["value1", "value2", "value3"]; // 用Set构造器将Set转换为Array var mySet = new Set(myArray); console.log(mySet.has("value1")); // true
Set.prototype.add()
mySet.add(value);
add() 方法用来给一个 Set 对象添加元素。
#
var mySet = new Set(); mySet.add(1); mySet.add(5).add("some text"); // 可以链式调用 console.log(mySet); // Set [1, 5, "some text"]
WeakSet
new WeakSet([iterable]);
一个 WeakSet 对象是一个无序的集合, 可以用它来存储任意的对象值,
并且对这些对象值保持弱引用.
它和 Set 对象的区别有两点:
1.WeakSet 对象中只能存放对象值, 不能存放原始值, 而 Set 对象都可以.
2.WeakSet 对象中存储的对象值都是被弱引用的, 如果没有其他的变量或属性引用这个对象值,
则这个对象值会被当成垃圾回收掉. 正因为这样, WeakSet 对象是无法被枚举的, 没有办法拿到它包含的所有元素.
WeakSet.prototype.add(value)
WeakSet.prototype.delete(value)
WeakSet.prototype.has(value)
#
var ws = new WeakSet(); var obj = {}; var foo = {}; ws.add(window); ws.add(obj); console.log(ws.has(window)); // true console.log(ws.has(foo)); // false foo has not been added to the set ws.delete(window); // removes window from the set console.log(ws.has(window)); // false window has been removed