Skip to content

Commit b025c97

Browse files
committed
update proxy blog 🚜 🍿 🌟
1 parent 6404b70 commit b025c97

File tree

1 file changed

+28
-14
lines changed

1 file changed

+28
-14
lines changed

Blog/58.ES6 Proxy 实用代码示例.md

+28-14
Original file line numberDiff line numberDiff line change
@@ -51,9 +51,12 @@ const o = defaultProp({ name: 'default name'})
5151

5252
test() // name = "default name", name not in o
5353

54+
// 替换默认值
5455
o.name = 'abcdef'
5556
test() // name = "abcdef", name in o
5657

58+
59+
// 删除name属性后 使用默认值
5760
delete o.name
5861
test() // name = "default name", name not in o
5962

@@ -64,9 +67,10 @@ test() // name = "default name", name not in o
6467

6568
Proxy 也有利于限制属性的访问,比如隐藏以下划线开头的的属性,让他们真正私有化。
6669

67-
上面两个例子相对简单,这个的代码就麻烦点了,先上代码,后面解释:
70+
先上代码,后面解释:
6871

6972
```js
73+
// filter参数作为一个过滤函数出入
7074
function priavateProp(obj, filter){
7175
const handler = {
7276
get(obj, prop) {
@@ -94,7 +98,14 @@ function priavateProp(obj, filter){
9498

9599
return new Proxy(obj, handler)
96100
}
97-
// 私有属性过滤器
101+
102+
```
103+
104+
上面代码使用了4个 trap 函数来实现,参数 `filter` 函数是用来过滤私有属性的过滤器。`has` 函数因为在 Proxy 中用来监听对象 `in` 的使用,所以成了过滤私有属性的核心。`ownKeys` 过滤私有属性,让 `Object.keys(p)` 返回其他所有属性。
105+
106+
```js
107+
// 私有属性过滤器
108+
// 规则:以 _ 为开头的属性都是私有属性
98109
function filter(prop){
99110
return prop.indexOf('_') === 0
100111
}
@@ -114,6 +125,7 @@ console.log(p) // Proxy {_private: "private property", name: "public name"}
114125

115126
p._private // undefined
116127
JSON.stringify(p) // "{"name":"public name"}"
128+
117129
// 只能内部访问私有属性
118130
p.say() // private property
119131

@@ -122,13 +134,13 @@ console.log('_private' in p) // false
122134
// 不能遍历到私有属性
123135
Object.keys(p) // ["name", "say"]
124136

137+
// 私有属性不能赋值
125138
p._private = '000' // Uncaught Error: cannot set property _private
126139

127140
```
128141

129-
上面代码使用了4个 trap 函数来实现,参数 `filter` 函数是用来过滤私有属性的过滤器。`has` 函数因为在 Proxy 中用来监听对象 `in` 的使用,所以成了过滤私有属性的核心。`ownKeys` 过滤私有属性,让 `Object.keys(p)` 返回其他所有属性。
130142

131-
注意,因为在 Proxy 上调用方法, `this` 默认指向的是 Proxy ,而不是原始对象,因此方法将无法访问私有属性,所以通过将方法绑定到 `get` 函数中来解决。
143+
注意,因为在 Proxy 上调用方法, `this` 默认指向的是 Proxy 代理 ,而不是原始对象,因此方法将无法访问私有属性,所以通过将方法绑定到 `get` 函数中来解决。
132144

133145

134146
## 枚举 Enum
@@ -267,12 +279,11 @@ obj.key('x') // undefined
267279

268280
## 追踪对象和数组
269281

270-
这也是观察者模式的一部分,同时 Vue.js 在今年(2017)也会实现一个基于 Proxy 的 Observation
282+
这也是观察者模式的一部分
283+
在 Vue.js 中无法监听数组的 `length` 导致 `arr.length = 1` 这种数据的改变无法监听,因此 Vue.js 在今年(2017)也会实现一个基于 Proxy 的 Observation
271284

272285
当对象或数组发生变化时,我们通过订阅的事件就可以观察到,同理,我们还可以添加验证的拦截,在数据更改之前先做验证处理。
273286

274-
在 Vue.js 中无法监听数组的 `length` 导致 `arr.length = 1` 这种数据的改变无法监听
275-
276287
因此我们把对象和数组也加一层 Proxy 来处理,我们把所有的改变都转发到原对象上,在修改或删除之后添加一个函数当做监听器 :
277288

278289
```js
@@ -407,7 +418,7 @@ p2.value // "proxy value" p1 p2 引用同一个实例对象
407418

408419
一旦某个代理对象被撤销,它将变的几乎完全不可用,在它身上执行任何的可代理操作都会抛出 TypeError 异常。
409420

410-
所以,利用 `Proxy.revocable` 实现一个验证和可撤销访问的例子
421+
`Proxy.revocable`的一个使用场景是,目标对象不允许直接访问,必须通过代理访问,一旦访问结束,就收回代理权,不允许再次访问。所以,利用 `Proxy.revocable` 实现一个验证和可撤销访问的例子
411422

412423
```js
413424
const revocableInfo = Proxy.revocable({}, {
@@ -467,7 +478,7 @@ setUser(revocableInfo.proxy)
467478
// TypeError: must be "name" or "age"
468479

469480

470-
// 代理对象执行撤销方法
481+
// 代理对象执行撤销方法 收回代理权
471482
revocableInfo.revoke()
472483
setUserAgain()
473484
// TypeError: Cannot perform 'set' on a proxy that has been revoked
@@ -477,13 +488,16 @@ setUserAgain()
477488
某个代理对象一旦被撤销,这个代理对象永远不可能恢复到原来的状态,同时和它关联的目标对象以及处理器对象将有可能被垃圾回收掉。
478489

479490

491+
## 最后
492+
493+
Proxy 是在目标对象之前加一层劫持,外界对该对象的访问,都必须先通过这层劫持,因此提供了一种机制,可以对外界的访问进行过滤和改写,等同于在语言层面做出修改,所以属于一种 『元编程』
480494

481-
### 参考文章
495+
> 参考文章、代码
482496
483-
* [MDN Proxy](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Proxy)
484-
* [http://es6.ruanyifeng.com/#docs/proxy](http://es6.ruanyifeng.com/#docs/proxy)
485-
* [http://es6.ruanyifeng.com/#docs/reflect](http://es6.ruanyifeng.com/#docs/reflect)
486-
* [http://dealwithjs.io/es6-features-10-use-cases-for-proxy/](http://dealwithjs.io/es6-features-10-use-cases-for-proxy/)
497+
> * [MDN Proxy](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Proxy)
498+
> * [http://es6.ruanyifeng.com/#docs/proxy](http://es6.ruanyifeng.com/#docs/proxy)
499+
> * [http://es6.ruanyifeng.com/#docs/reflect](http://es6.ruanyifeng.com/#docs/reflect)
500+
> * [http://dealwithjs.io/es6-features-10-use-cases-for-proxy/](http://dealwithjs.io/es6-features-10-use-cases-for-proxy/)
487501
488502

489503

0 commit comments

Comments
 (0)