Set和Map
Set
const set = new Set([1, 2, 3, 4, 4]);
[...set]
// [1, 2, 3, 4]
let set = new Set();
set.add({});
set.size // 1
set.add({});
set.size // 2
//两个对象总是不相等的。
//转化:
const items = new Set([1, 2, 3, 4, 5]);
const array = Array.from(items);
基本可以使用数组的功能:
let a = new Set([1, 2, 3]);
let b = new Set([4, 3, 2]);
// 并集
let union = new Set([...a, ...b]);
// Set {1, 2, 3, 4}
// 交集
let intersect = new Set([...a].filter(x => b.has(x)));
// set {2, 3}
// (a 相对于 b 的)差集
let difference = new Set([...a].filter(x => !b.has(x)));
// Set {1}
WeakSet
WeakSet()参数只能为对象,而不能是其它类型,优点是存储dom节点而不用担心在节点从文档移除时,会引发内存泄漏问题。
Map
const m = new Map();
const o = {p: 'Hello World'};
m.set(o, 'content')
m.get(o) // "content"
m.has(o) // true
m.delete(o) // true
m.has(o) // false
//对于不同对象实例,无法获取对应的值,键实际上和内存地址绑定
const map = new Map();
map.set(['a'], 555);
map.get(['a']) // undefined
//链式
let map = new Map()
.set(1, 'a')
.set(2, 'b')
.set(3, 'c');
其它情况下,严格相等的(0和-0)都会被当作一个键,NaN也会被当作相等。
//也可以使用拓展
const map0 = new Map()
.set(1, 'a')
.set(2, 'b')
.set(3, 'c');
const map1 = new Map(
[...map0].filter(([k, v]) => k < 3)
);
WeakMap
只接受对象作为键名,且不计入垃圾回收,为了防止内存泄漏,所引用的键的对象会可能在未来消失,即消除外部多余引用,而不清除内部的
const wm = new WeakMap();
let key = {};
let obj = {foo: 1};
wm.set(key, obj);
obj = null;
wm.get(key)
// Object {foo: 1}
Proxy
使用Proxy设置访问拦截,相当于重载操作符
//第一个是被代理的目标,而handler是定义的拦截器
var proxy = new Proxy(target, handler);
var proxy = new Proxy({}, {
get: function(target, propKey) {
return 35;
}
});
proxy.time // 35
proxy.name // 35
proxy.title // 35
返回的结果指向原对象:
const proxy = new Proxy({}, {
get: function(target, key, receiver) {
return receiver;
}
});
const d = Object.create(proxy);
d.a === d // true
//禁止写操作
const handler = {
set: function(obj, prop, value, receiver) {
obj[prop] = receiver;
}
};
const proxy = new Proxy({}, handler);
const myObj = {};
Object.setPrototypeOf(myObj, proxy);
myObj.foo = 'bar';
myObj.foo === myObj // true
apply
拦截调用,三个参数是目标对象,目标对象上下文(this),目标对象的参数数组,一但出现函数调用,不论使用的是什么方法,都会被拦截。
has
拦截in运算符
var handler = {
has (target, key) {
if (key[0] === '_') {
return false;
}
return key in target;
}
};
var target = { _prop: 'foo', prop: 'foo' };
var proxy = new Proxy(target, handler);
'_prop' in proxy // false
construct
对于new命令拦截,参数是目标对象,构造函数参数对象,返回对象
此外还有:
- deleteProperty()拦截delete操作
- defineProperty()拦截对应的定义属性操作。
- ...其它同理.
Proxy.revocable()
返回一个可取消的Proxy实例。
let target = {};
let handler = {};
let {proxy, revoke} = Proxy.revocable(target, handler);
proxy.foo = 123;
proxy.foo // 123
revoke();//取消代理
//对于Proxy代理,this指向的是Proxy对象。
使用Proxy可以定义出拦截器,作为代理对象
function createWebService(baseUrl) {
return new Proxy({}, {
get(target, propKey, receiver) {
return () => httpGet(baseUrl + '/' + propKey);
}
});
}
const service = createWebService('http://example.com/data');
service.employees().then(json => {
const employees = JSON.parse(json);
// ···
});
Reflect
将部分Object中明显属于语言内部的方法放到Reflect对象上,一般用于对应的读取获取操作,反向获取属性和方法。
var myObject = {
foo: 4,
set bar(value) {
return this.foo = value;
},
};
var myReceiverObject = {
foo: 0,
};
Reflect.set(myObject, 'bar', 1, myReceiverObject);
myObject.foo // 4
myReceiverObject.foo // 1
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· Docker 太简单,K8s 太复杂?w7panel 让容器管理更轻松!