[译]ECMAScript 6中的集合类型,第三部分:WeakMap
2012-11-07 18:00
176 查看
原文:http://www.nczonline.net/blog/2012/11/06/ecmascript-6-collections-part-3-weakmaps/
一个
ECMAScript 6中的
在这个例子中,我们存储了一个键值对.键是一个DOM元素,存储着一个对应的字符串值.随后把那个DOM元素传入
这个例子有点误导,因为在第二次调用
译者注:由于语文水平实在有限,上面的这段话我无法表达清楚.所以我用我拙劣的水平做了几张图,希望我的理解是对的,也希望你能看懂.
变量map和element各自引用了一个对象.
map中添加了一个键值对,这个键和变量element同时指向一个DOM对象,只是一个是强引用,一个是弱引用.
强引用全部主动断掉,最后剩下的弱引用也自动断掉,孤立的DOM元素被回收,WeakMap对象中对应的键值对被自动清除.如果是常规的Map,由于不是弱引用,所以那个DOM对象不会被回收,仍然存在,仍然可以通过get()方法访问到.
使用
在大多数情况下,使用常规的
WeakMap类似于常规的
Map的一点是,它们都是把一个值映射到某个唯一的键上,然后就可以使用这个键获取到与之对应的值.
WeakMap和
Map不同的地方是,它的键只能是对象值而不可以是原始值.虽然这个限制看起来很奇怪,但正是这一点,才让
WeakMap变得很有价值.
一个
WeakMap对象的键只持有其所引用对象的弱引用,弱引用的特点是,它不能阻止垃圾回收器回收其引用的对象.当那个对象被垃圾回收器销毁后,
WeakMap对象中引用它的那个键值对也会被删除.使用
WeakMap最典型的例子就是用在要创建一个与特定的DOM元素相关联的对象的时候.例如,jQuery在程序内部维护着一些对象的缓存,每个缓存引用着一个DOM元素.使用
WeakMap的话,jQuery就可以在某些DOM元素被从文档中删除后就自动释放它们先前占用的内存.
ECMAScript 6中的
WeakMap类型是一个无序的键值对列表,键必须是一个非null的对象(non-null object),值可以是任意类型.
WeakMap的API很简单,和
Map一样,
set()和
get()分别用来添加数据和获取数据:
var map = new WeakMap(), element = document.querySelector(".element"); map.set(element, "Original"); // 下面就可以使用了 var value = map.get(element); console.log(value); // "Original" // 下面删除引用 element.parentNode.removeChild(element); element = null; //译者注:下面这句实际上会报错(value is not a non-null object),因为键必须是非null的对象.作者只是为了讲解,看下面. value = map.get(element); console.log(value); // undefined
在这个例子中,我们存储了一个键值对.键是一个DOM元素,存储着一个对应的字符串值.随后把那个DOM元素传入
get()方法来获取到存储的字符串值.如果这个DOM元素被从文档中删除了,指向它的变量也被赋值为
null,然后
WeakMap对象中的那个键值对会被自动删除,这时如果再读取那个键值对的话,就会失败.
这个例子有点误导,因为在第二次调用
map.get(element)的时候,实际上是把
null(
element被赋的值)而不是DOM元素的引用传进去了.你不能使用
null来作为
WeakMap对象的键(WeakMap的键只能是对象,null不是对象),这样的代码是会抛出异常的,根本不会执行到console.log语句.上面的代码之所以那么写,只是为了讲解.想要说明那个键值对已经不存在了.不过不幸的是,我们没有任何办法来检测这个键值对是否真的被删除了(因为
element的值已经是
null,我们无法获取到指向那个DOM元素的引用了,假如真能获取到那个DOM对象的引用,传给get方法的话,应该返回undefined).
译者注:由于语文水平实在有限,上面的这段话我无法表达清楚.所以我用我拙劣的水平做了几张图,希望我的理解是对的,也希望你能看懂.
var map = new WeakMap(), element = document.querySelector(".element");
变量map和element各自引用了一个对象.
map.set(element, "Original");
map中添加了一个键值对,这个键和变量element同时指向一个DOM对象,只是一个是强引用,一个是弱引用.
element.parentNode.removeChild(element); element = null;
强引用全部主动断掉,最后剩下的弱引用也自动断掉,孤立的DOM元素被回收,WeakMap对象中对应的键值对被自动清除.如果是常规的Map,由于不是弱引用,所以那个DOM对象不会被回收,仍然存在,仍然可以通过get()方法访问到.
WeakMap对象还有一个
has()方法,可以判断某个对象引用是否作为了自己的键,还有
delete()方法,用来删除一个键值对.
var map = new WeakMap(), element = document.querySelector(".element");map.set(element, "Original");
console.log(map.has(element)); // true
console.log(map.get(element)); // "Original"
map.delete(element);
console.log(map.has(element)); // false
console.log(map.get(element)); // undefined
使用
delete()方法删除某个键后,再执行
has()方法的时候会返回
false,执行
get()方法会返回
undefined.
浏览器支持
Firefox和Chrome都已经实现了WeakMap,可是,在Chrome中,你必须手动开启ECMAScript 6特性:打开
chrome://flags勾选"启用实验性 JavaScript".目前浏览器的实现都完全遵循了当前的strawman[1]规范(而ECMAScript 6的最新草案新添加了一个
WeakMap.prototype.clear()方法,这两个浏览器目前还都没实现).
用途和限制
目前WeakMap有一个特定的使用情境,那就是在将值映射到一些未来可能被会删除的对象上的时候.
WeakMap的这种"能释放某些无用对象所占用的内存的能力"对于那种将DOM元素包装成为某种自定义对象的JavaScript库来说是很有用的(比如jQuery和YUI).在未来,
WeakMap的标准完全实现且被广泛使用之后,应该会有更多的能用到
WeakMap的地方,所以在短期内,不要因为想不到使用
WeakMap的好点子而苦恼.
在大多数情况下,使用常规的
Map应该是你最合适的选择.
WeakMap有不少限制,比如不能枚举键值对(
for of),也不能得知它们到底包含了多少个键值对(
size).如果你需要这样做,那么就使用常规的
Map.如果你仅仅需要把一些对象作为键,且不需要其他更多的功能,那么
WeakMap是个好的选择.
参考
WeakMapsStrawman (ECMA)相关文章推荐
- [译]ECMAScript 6中的集合类型,第二部分:Map
- 第三部分 类型设计------《Microsoft.NET框架程序设计》
- 代码大全第二版读书笔记 第三部分-变量 十二、基本数据类型 十三、不常见的数据类型
- C#语言 第三部分 集合框架 IList,IList——向量(1)
- 第三部分 类型设计2------《Microsoft.NET框架程序设计》
- [译]ECMAScript 6中的集合类型,第一部分:Set
- python学习笔记-Day04-第三部分(内置函数,map,filter,reduce,yield)
- Hibernate之映射值类型集合(映射map)
- Java中Map的其他类型(WeakHashMap-IdentityHashMap-EnumMap)
- Hibernate 多表关联映射- Hibernate中使用的集合类型(set,list,array,bag,map)
- java 集合框架 - Map集合部分
- Spark SQL集合数据类型array\map的取值方式
- Java list、map、set、vector集合类型中的null值
- EL表达式取出Map集合中key为Integer类型的值,bug解决方案
- 黑马程序员-Map集合部分
- C++ STL 有关于SET集合部分 的自定义数据类型的排序 以及 pair的使用
- 整型-文件-方法名-日期-文件拷贝-缩略图-JSON创建-PDF-HTTP-单例-抓屏-目录-ZIP-XML-Map-邮件-Array-beanCopy-数组类型转换-数组集合转换-枚举示例
- Hibernate 多表关联映射- Hibernate中使用的集合类型(set,list,array,bag,map)
- (15)如何使用Cocos2d-x 3.0制作基于tilemap的游戏:第三部分(完)
- fastjson json字符串和JavaBean、List、Map及复杂集合类型的相互转换。