WeakMap/WeakSet
- 原型上不存在遍歷方法(沒有部署iterator接口)
- 成員只能是對象
- 垃圾回收機制不考慮對成員對象的應用
WeakSet/WeakMap 中的對象都是弱引用,即垃圾回收機制不考慮 WeakSet 對該對象的引用,也就是說,如果其他對象都不再引用該對象,那么垃圾回收機制會自動回收該對象所占用的內存,不考慮該對象還存在于 WeakSet 之中。
這是因為垃圾回收機制根據對象的可達性(reachability)來判斷回收,如果對象還能被訪問到,垃圾回收機制就不會釋放這塊內存。結束使用該值之后,有時會忘記取消引用,導致內存無法釋放,進而可能會引發內存泄漏。WeakSet 里面的引用,都不計入垃圾回收機制,所以就不存在這個問題。因此,WeakSet 適合臨時存放一組對象,以及存放跟對象綁定的信息。只要這些對象在外部消失,它在 WeakSet 里面的引用就會自動消失。
由于上面這個特點,WeakSet 的成員是不適合引用的,因為它會隨時消失。另外,由于 WeakSet 內部有多少個成員,取決于垃圾回收機制有沒有運行,運行前后很可能成員個數是不一樣的,而垃圾回收機制何時運行是不可預測的,因此 ES6 規定 WeakSet 不可遍歷。
Proxy
Proxy 可以理解成,在目標對象之前架設一層“攔截”,外界對該對象的訪問,都必須先通過這層攔截,因此提供了一種機制,可以對外界的訪問進行過濾和改寫。Proxy 這個詞的原意是代理,用在這里表示由它來“代理”某些操作,可以譯為“代理器”。
var proxy = new Proxy(target, handler);
- target參數表示所要攔截的目標對象,handler參數也是一個對象,用來定制攔截行為。
- 如果handler沒有設置任何攔截,那就等同于直接通向原對象。
- 用
Proxy
實例proxy
來訪問target
的屬性 - 一個技巧是將 Proxy 對象,設置到object.proxy屬性,從而可以在object對象上調用。
var object = { proxy: new Proxy(target, handler) };
- 雖然for…in循環也用到了in運算符,但是has()攔截對for…in循環不生效。
const star = {name: "Yoona Lim",age: 23,tel: 'star 666'
}
const agent = new Proxy(star, {get: function (target, key) {if (key === 'tel') {return 'rejected 110'} else {return target[key]}},set: function (target, key, val) {if (key === 'offerPrice') {if (val < 5000) {throw new ReferenceError('below standard!')} else {target[key] = val}} else {target[key] = val}},has: function (target, key) {console.log('走了has攔截')return target.hasOwnProperty(key)}
})
console.log(agent.name)
console.log(agent.age)
console.log(agent.tel)
agent.cute = true
console.log(agent.cute)
agent.offerPrice = 50000
console.log(agent.offerPrice)
console.log('offerPrice' in agent)
console.log('gender' in agent)
for (let key in agent) {console.log('for...in不走has攔截', agent[key])
}console.log(agent)console.log(star)
agent.offerPrice = 50
Reflect
Reflect對象的設計目的有這樣幾個。
(1) 將Object對象的一些明顯屬于語言內部的方法(比如Object.defineProperty),放到Reflect對象上。現階段,某些方法同時在Object和Reflect對象上部署,未來的新方法將只部署在Reflect對象上。也就是說,從Reflect對象上可以拿到語言內部的方法。
(2) 修改某些Object方法的返回結果,讓其變得更合理。比如,Object.defineProperty(obj, name, desc)在無法定義屬性時,會拋出一個錯誤,而Reflect.defineProperty(obj, name, desc)則會返回false。
(3) 讓Object操作都變成函數行為。某些Object操作是命令式,比如name in obj和delete obj[name],而Reflect.has(obj, name)和Reflect.deleteProperty(obj, name)讓它們變成了函數行為。