JS - ES2015/ES6新特性详解2(Set, WeakSet, Map, WeakMap、箭头函数)
相关文章系列:
JS - ES2015/ES6新特性详解1(let、const、For..of循环、迭代器、生成器)
[当前文章] JS - ES2015/ES6新特性详解2(Set, WeakSet, Map, WeakMap、箭头函数)
JS - ES2015/ES6新特性详解3(默认参数、不定参数、扩展运算符、解构)
JS - ES2015/ES6新特性详解4(类、模块、Promises、模板字符串)
JS - ES2015/ES6新特性详解5(代理、反射、Symbols、Unicode编码)
JS - ES2015/ES6新特性详解6(二进制和八进制、尾调用、其他新增的API)
JS - ES2015/ES6新特性详解1(let、const、For..of循环、迭代器、生成器)
[当前文章] JS - ES2015/ES6新特性详解2(Set, WeakSet, Map, WeakMap、箭头函数)
JS - ES2015/ES6新特性详解3(默认参数、不定参数、扩展运算符、解构)
JS - ES2015/ES6新特性详解4(类、模块、Promises、模板字符串)
JS - ES2015/ES6新特性详解5(代理、反射、Symbols、Unicode编码)
JS - ES2015/ES6新特性详解6(二进制和八进制、尾调用、其他新增的API)
五、Set 和 WeakSet
1,Set
Set 类似于数组,但是成员变量的值都是唯一的,没有重复的值。
(1)下面是一个简单的样例
(2)运行结果如下:
var set = new Set(); set.add("桔子").add("葡萄").add("西瓜"); console.log(set.size) console.log(set.has("葡萄")) for(var item of set) { console.log(item) }
(2)运行结果如下:
2,WeakSet
- WeakSet 类似于 Set,也是不重复的值的集合。但是它只能用于存储对象。而不能是其他类型的值。没有引用的对象将被垃圾回收。
- 因为成员都是弱引用,随时可能消失,遍历不能保证成员的存在。所以 WeakSet 不能遍历。
(1)下面是一个简单的使用样例
var item = {a:"苹果"} var set = new WeakSet(); set.add({ a:"桔子"}).add(item).add({ a:"葡萄"}).add({ a:"西瓜"}); console.log(set.size) console.log(set.has({a:"桔子"})) console.log(set.has(item)) for(let item of set) { console.log(item) }
(2)运行结果如下:
六、Map 和 WeakMap
1,Map
Map 对象是一种有对应 键/值 对的对象, 虽然 JS 的 Object 也是 键/值 对的对象,但二者有如下区别:
- Object 对象有原型, 也就是说他有默认的 key 值在对象上面, 除非我们使用 Object.create(null) 创建一个没有原型的对象
- 在 Object 对象中, 只能把 String 和 Symbol 作为 key 值。但是在 Map 中,key 值可以是任何基本类型(String, Number, Boolean, undefined, NaN....),或者对象(Map, Set, Object, Function , Symbol , null....)。
- 通过 Map 中的 size 属性, 可以很方便地获取到 Map 长度。要获取 Object 的长度, 你只能用别的方法了。
var map = new Map(); map.set("土豆", 12); map.set("西瓜", 34); console.log(map.get("土豆")) //遍历key for (var key of map.keys()) { console.log(key) } //遍历元素 for(let item of map) { console.log(item) }运行结果如下:
(2)使用对象作为 key
var map = new Map(); var key = {a: "a"} map.set(key, 12); console.log(map.get(key)) console.log(map.get({a: "a"}))运行结果如下:
2,WeakMap
WeakMap 是弱引用的 Map 对象, 如果对象在 js 执行环境中不存在引用的话,相对应的 WeakMap 对象内的该对象也会被 js 执行环境回收。它与 Map 还有如下区别:
- WeakMap 不接受基本类型的值作为键名。它只接受对象作为键名,而且键名所指向的对象, 不计入垃圾回收机制。
- WeakMap 没有 keys、values、entries 和 size 方法。
- WeakMap 没有没有遍历操作,也无法遍历。
var wm = new WeakMap(); var o1 = {} var o2 = {} var o3 = {} wm.set(o1, 1); wm.set(o2, 2); wm.set(o3, {a: "航歌"}); wm.set({}, 4); console.log(wm.get(o2)); console.log(wm.has({})) delete o2; console.log(wm.get(o3)); //遍历key(报错) for (var key of wm.keys()) { console.log(key) } //遍历元素(报错) for(let item of wm) { console.log(item) }
(2)运行结果如下:
七、箭头函数(arrow function)
1,箭头函数可以简化匿名函数的写法
//ES5 的写法 function(x, y) { x++; y--; return x + y; } //ES6 的写法 (x, y) => {x++; y--; return x+y}
2,箭头函数中的this对象是定义时所在的对象
(1)过去我们在对象方法中使用 this,必须非常小心。比如下面代码:class Hangge { constructor(){ this.site = 'hangge.com' } says(say){ setTimeout(function(){ console.log(this.site + say) }, 1000) } } var hangge = new Hangge() hangge.says('欢迎您!') //undefined欢迎您!上面代码运行结果可能并不像我们想象的那样,这是因为 setTimeout 中的 this 指向的是全局对象,即运行时的对象。
为了让它能够正确的运行,传统的解决方法有两种。一种方法是:将 this 传给一个临时的 _this,再用 _this 来指代 this。
class Hangge { constructor(){ this.site = 'hangge.com' } says(say){ var _this = this; setTimeout(function(){ console.log(_this.site + say) }, 1000) } } var hangge = new Hangge() hangge.says('欢迎您!') //hangge.com欢迎您!
另一种方法是:使用 bind(this)
class Hangge { constructor(){ this.site = 'hangge.com' } says(say){ setTimeout(function(){ console.log(this.site + say) }.bind(this), 1000) } } var hangge = new Hangge() hangge.says('欢迎您!') //hangge.com欢迎您!
(2)如果使用箭头函数就方便多了。其函数体内的 this 对象,就是定义时所在的对象,而不是使用时所在的对象。这并不是因为箭头函数内部有绑定 this 的机制,其实是因为箭头函数根本没有自己的 this,它的 this 是继承外面的,因此内部的 this 就是外层代码块的 this。
class Hangge { constructor(){ this.site = 'hangge.com' } says(say){ setTimeout( () => { console.log(this.site + say) }, 1000) } } var hangge = new Hangge() hangge.says('欢迎您!') //hangge.com欢迎您!