重温基础:ES6系列(四)

640?wx_fmt=png

ES6系列目录

  • 1 let 和 const命令

  • 2 变量的解构赋值

  • 3 字符串的拓展

  • 4 正则的拓展

  • 5 数值的拓展

  • 6 函数的拓展

  • 7 数组的拓展

  • 8 对象的拓展

  • 9 Symbol

  • 10 Set和Map数据结构

  • 11 Proxy

  • 12 Promise对象

  • 13 Iterator和 for...of循环

  • 14 Generator函数和应用

  • 15 Class语法和继承

  • 16 Module语法和加载实现


所有整理的文章都收录到我《Cute-JavaScript》系列文章中,访问地址:http://js.pingan8787.com

10 Set和Map数据结构

10.1 Set

介绍:Set数据结构类似数组,但所有成员的值唯一Set本身为一个构造函数,用来生成 Set数据结构,使用 add方法来添加新成员。

let a = new Set();	
[1,2,2,1,3,4,5,4,5].forEach(x=>a.add(x));	
for(let k of a){	
    console.log(k)	
};	
// 1 2 3 4 5

基础使用

let a = new Set([1,2,3,3,4]);	
[...a]; // [1,2,3,4]	
a.size; // 4	
// 数组去重	
[...new Set([1,2,3,4,4,4])];// [1,2,3,4]

注意

  • 向 Set中添加值的时候,不会类型转换,即 5和 '5'是不同的。

[...new Set([5,'5'])]; // [5, "5"]

属性和方法

  • 属性:

    • Set.prototype.constructor:构造函数,默认就是 Set函数。

    • Set.prototype.size:返回 Set实例的成员总数。

  • 操作方法:

    • add(value):添加某个值,返回 Set 结构本身。

    • delete(value):删除某个值,返回一个布尔值,表示删除是否成功。

    • has(value):返回一个布尔值,表示该值是否为Set的成员。

    • clear():清除所有成员,没有返回值。

let a = new Set();	
a.add(1).add(2); // a => Set(2) {1, 2}	
a.has(2);        // true	
a.has(3);        // false	
a.delete(2);     // true  a => Set(1) {1}	
a.clear();       // a => Set(0) {}

数组去重

let a = new Set([1,2,3,3,3,3]);

10.2 Set的应用

数组去重

// 方法1	
[...new Set([1,2,3,4,4,4])]; // [1,2,3,4]	
// 方法2	
Array.from(new Set([1,2,3,4,4,4]));    // [1,2,3,4]

遍历和过滤

let a = new Set([1,2,3,4]);	
// map 遍历操作	
let b = new Set([...a].map(x =>x*2));// b => Set(4) {2,4,6,8}	
// filter 过滤操作	
let c = new Set([...a].filter(x =>(x%2) == 0)); // b => Set(2) {2,4}

获取并集、交集和差集

let a = new Set([1,2,3]);	
let b = new Set([4,3,2]);	
// 并集	
let c1 = new Set([...a, ...b]);  // Set {1,2,3,4}	
// 交集	
let c2 = new Set([...a].filter(x => b.has(x))); // set {2,3}	
// 差集	
let c3 = new Set([...a].filter(x => !b.has(x))); // set {1}
  • 遍历方法:

    • keys():返回键名的遍历器。

    • values():返回键值的遍历器。

    • entries():返回键值对的遍历器。

    • forEach():使用回调函数遍历每个成员

Set遍历顺序是插入顺序,当保存多个回调函数,只需按照顺序调用。但由于 Set结构没有键名只有键值,所以 keys()values()是返回结果相同。

let a = new Set(['a','b','c']);	
for(let i of a.keys()){console.log(i)};   // 'a' 'b' 'c'	
for(let i of a.values()){console.log(i)}; // 'a' 'b' 'c'	
for(let i of a.entries()){console.log(i)}; 	
// ['a','a'] ['b','b'] ['c','c']

并且 还可以使用 for...of直接遍历 Set

let a = new Set(['a','b','c']);	
for(let k of a){console.log(k)};   // 'a' 'b' 'c'

forEach与数组相同,对每个成员执行操作,且无返回值。

let a = new Set(['a','b','c']);	
a.forEach((v,k) => console.log(k + ' : ' + v));

10.3 Map

由于传统的 JavaScript对象只能用字符串当做键,给开发带来很大限制,ES6增加 Map数据结构,使得各种类型的值(包括对象)都可以作为键。Map结构提供了“值—值”的对应,是一种更完善的 Hash 结构实现。基础使用

let a = new Map();	
let b = {name: 'leo' };	
a.set(b,'my name'); // 添加值	
a.get(b);           // 获取值	
a.size;      // 获取总数	
a.has(b);    // 查询是否存在	
a.delete(b); // 删除一个值	
a.clear();   // 清空所有成员 无返回

注意

  • 传入数组作为参数,指定键值对的数组

let a = new Map([	
    ['name','leo'],	
    ['age',18]	
])
  • 如果对同一个键多次赋值,后面的值将覆盖前面的值

let a = new Map();	
a.set(1,'aaa').set(1,'bbb');	
a.get(1); // 'bbb'
  • 如果读取一个未知的键,则返回 undefined

new Map().get('abcdef'); // undefined
  • 同样的值的两个实例,在 Map 结构中被视为两个键。

let a = new Map();	
let a1 = ['aaa'];	
let a2 = ['aaa'];	
a.set(a1,111).set(a2,222);	
a.get(a1); // 111	
a.get(a2); // 222

遍历方法: Map 的遍历顺序就是插入顺序。

  • keys():返回键名的遍历器。

  • values():返回键值的遍历器。

  • entries():返回所有成员的遍历器。

  • forEach():遍历 Map 的所有成员。

let a = new Map([	
    ['name','leo'],	
    ['age',18]	
])	
for (let i of a.keys()){...};	
for (let i of a.values()){...};	
for (let i of a.entries()){...};	
a.forEach((v,k,m)=>{	
    console.log(`key:${k},value:${v},map:${m}`)	
})

将Map结构转成数组结构

let a = new Map([	
    ['name','leo'],	
    ['age',18]	
])	
let a1 = [...a.keys()];   // a1 => ["name", "age"]	
let a2 = [...a.values()]; // a2 =>  ["leo", 18]	
let a3 = [...a.entries()];// a3 => [['name','leo'], ['age',18]]

10.4 Map与其他数据结构互相转换

  • Map 转 数组

let a = new Map().set(true,1).set({f:2},['abc']);	
[...a]; // [[true:1], [ {f:2},['abc'] ]]
  • 数组 转 Map

let a = [ ['name','leo'], [1, 'hi' ]]	
let b = new Map(a);
  • Map 转 对象 如果所有 Map 的键都是字符串,它可以无损地转为对象。

function fun(s) {	
  let obj = Object.create(null);	
  for (let [k,v] of s) {	
    obj[k] = v;	
  }	
  return obj;	
}	
const a = new Map().set('yes', true).set('no', false);	
fun(a)	
// { yes: true, no: false }
  • 对象 转 Map

function fun(obj) {	
  let a = new Map();	
  for (let k of Object.keys(obj)) {	
    a.set(k, obj[k]);	
  }	
  return a;	
}	
fun({yes: true, no: false})	
// Map {"yes" => true, "no" => false}
  • Map 转 JSON(1)Map键名都是字符串,转为对象JSON:

function fun (s) {	
    let obj = Object.create(null);	
    for (let [k,v] of s) {	
        obj[k] = v;	
    }	
    return JSON.stringify(obj)	
}	
let a = new Map().set('yes', true).set('no', false);	
fun(a);	
// '{"yes":true,"no":false}'

(2)Map键名有非字符串,转为数组JSON:

function fun (map) {	
  return JSON.stringify([...map]);	
}	
let a = new Map().set(true, 7).set({foo: 3}, ['abc']);	
fun(a)	
// '[[true,7],[{"foo":3},["abc"]]]'
  • JSON 转 Map(1)所有键名都是字符串:

function fun (s) {	
  let strMap = new Map();	
  for (let k of Object.keys(s)) {	
    strMap.set(k, s[k]);	
  }	
  return strMap;	
  return JSON.parse(strMap);	
}	
fun('{"yes": true, "no": false}')	
// Map {'yes' => true, 'no' => false}

(2)整个 JSON 就是一个数组,且每个数组成员本身,又是一个有两个成员的数组:

function fun2(s) {	
  return new Map(JSON.parse(s));	
}	
fun2('[[true,7],[{"foo":3},["abc"]]]')	
// Map {true => 7, Object {foo: 3} => ['abc']}

11 Proxy

proxy 用于修改某些操作的默认行为,可以理解为一种拦截外界对目标对象访问的一种机制,从而对外界的访问进行过滤和修改,即代理某些操作,也称“代理器”。

11.1 基础使用

proxy实例化需要传入两个参数, target参数表示所要拦截的目标对象, handler参数也是一个对象,用来定制拦截行为。

let p = new Proxy(target, handler);	
let a = new Proxy({}, {	
    get: function (target, handler){	
        return 'leo';	
    }	
})	
a.name; // leo	
a.age;  // leo	
a.abcd; // leo

上述 a实例中,在第二个参数中定义了 get方法,来拦截外界访问,并且 get方法接收两个参数,分别是目标对象所要访问的属性,所以不管外部访问对象中任何属性都会执行 get方法返回 leo注意

  • 只能使用 Proxy实例的对象才能使用这些操作。

  • 如果 handler没有设置拦截,则直接返回原对象。

let target = {};	
let handler = {};	
let p = new Proxy(target, handler);	
p.a = 'leo'; 	
target.a;  // 'leo'

同个拦截器函数,设置多个拦截操作

let p = new Proxy(function(a, b){	
    return a + b;	
},{	
    get:function(){	
        return 'get方法';	
    },	
    apply:function(){	
        return 'apply方法';	
    }	
})

这里还有一个简单的案例:

let handler = {	
    get : function (target, name){	
        return name in target ? target[name] : 16;	
    }	
}	
let p = new Proxy ({}, handler);	
p.a = 1;	
console.log(p.a , p.b);	
// 1   16

这里因为 p.a=1 定义了 p中的 a属性,值为 1,而没有定义 b属性,所以 p.a会得到 1,而 p.b会得到 undefined从而使用 nameintarget?target[name]:16;返回的默认值 16

Proxy支持的13种拦截操作

  • get(target,propKey,receiver): 拦截对象属性的读取,比如proxy.foo和proxy['foo']。

  • set(target,propKey,value,receiver): 拦截对象属性的设置,比如proxy.foo = v或proxy['foo'] = v,返回一个布尔值。

  • has(target,propKey): 拦截propKey in proxy的操作,返回一个布尔值。

  • deleteProperty(target,propKey): 拦截delete proxy[propKey]的操作,返回一个布尔值。

  • ownKeys(target): 拦截Object.getOwnPropertyNames(proxy)、Object.getOwnPropertySymbols(proxy)、Object.keys(proxy)、for...in循环,返回一个数组。该方法返回目标对象所有自身的属性的属性名,而Object.keys()的返回结果仅包括目标对象自身的可遍历属性。

  • getOwnPropertyDescriptor(target,propKey): 拦截Object.getOwnPropertyDescriptor(proxy, propKey),返回属性的描述对象。

  • defineProperty(target,propKey,propDesc): 拦截Object.defineProperty(proxy, propKey, propDesc)、Object.defineProperties(proxy, propDescs),返回一个布尔值。

  • preventExtensions(target): 拦截Object.preventExtensions(proxy),返回一个布尔值。

  • getPrototypeOf(target): 拦截Object.getPrototypeOf(proxy),返回一个对象。

  • isExtensible(target): 拦截Object.isExtensible(proxy),返回一个布尔值。

  • setPrototypeOf(target,proto): 拦截Object.setPrototypeOf(proxy, proto),返回一个布尔值。如果目标对象是函数,那么还有两种额外操作可以拦截。

  • apply(target,object,args): 拦截 Proxy 实例作为函数调用的操作,比如proxy(...args)、proxy.call(object, ...args)、proxy.apply(...)。

  • construct(target,args): 拦截 Proxy 实例作为构造函数调用的操作,比如new proxy(...args)。

11.2 取消Proxy实例

使用 Proxy.revocale方法取消 Proxy实例。

let a = {};	
let b = {};	
let {proxy, revoke} = Proxy.revocale(a, b);	
proxy.name = 'leo';  // 'leo'	
revoke();	
proxy.name;  // TypeError: Revoked

11.3 实现 Web服务的客户端

const service = createWebService('http://le.com/data');	
service.employees().than(json =>{	
    const employees = JSON.parse(json);	
})	
function createWebService(url){	
    return new Proxy({}, {	
        get(target, propKey, receiver{	
            return () => httpGet(url+'/'+propKey);	
        })	
    })	
}


扫一扫 关注我的公众号【前端名狮】,更多精彩内容陪伴你!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值