当前位置: > > > JS - ES2015/ES6新特性详解2(Set, WeakSet, Map, WeakMap、箭头函数)

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)

五、Set 和 WeakSet

1,Set

Set 类似于数组,但是成员变量的值都是唯一的,没有重复的值。
(1)下面是一个简单的样例
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 的长度, 你只能用别的方法了。
(1)使用字符串作为 key
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 没有 keysvaluesentries size 方法。
  • WeakMap 没有没有遍历操作,也无法遍历。
(1)下面是一个简单的样例
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欢迎您!
评论0