@@ -51,9 +51,12 @@ const o = defaultProp({ name: 'default name'})
51
51
52
52
test () // name = "default name", name not in o
53
53
54
+ // 替换默认值
54
55
o .name = ' abcdef'
55
56
test () // name = "abcdef", name in o
56
57
58
+
59
+ // 删除name属性后 使用默认值
57
60
delete o .name
58
61
test () // name = "default name", name not in o
59
62
@@ -64,9 +67,10 @@ test() // name = "default name", name not in o
64
67
65
68
Proxy 也有利于限制属性的访问,比如隐藏以下划线开头的的属性,让他们真正私有化。
66
69
67
- 上面两个例子相对简单,这个的代码就麻烦点了, 先上代码,后面解释:
70
+ 先上代码,后面解释:
68
71
69
72
``` js
73
+ // filter参数作为一个过滤函数出入
70
74
function priavateProp (obj , filter ){
71
75
const handler = {
72
76
get (obj , prop ) {
@@ -94,7 +98,14 @@ function priavateProp(obj, filter){
94
98
95
99
return new Proxy (obj, handler)
96
100
}
97
- // 私有属性过滤器
101
+
102
+ ```
103
+
104
+ 上面代码使用了4个 trap 函数来实现,参数 ` filter ` 函数是用来过滤私有属性的过滤器。` has ` 函数因为在 Proxy 中用来监听对象 ` in ` 的使用,所以成了过滤私有属性的核心。` ownKeys ` 过滤私有属性,让 ` Object.keys(p) ` 返回其他所有属性。
105
+
106
+ ``` js
107
+ // 私有属性过滤器
108
+ // 规则:以 _ 为开头的属性都是私有属性
98
109
function filter (prop ){
99
110
return prop .indexOf (' _' ) === 0
100
111
}
@@ -114,6 +125,7 @@ console.log(p) // Proxy {_private: "private property", name: "public name"}
114
125
115
126
p ._private // undefined
116
127
JSON .stringify (p) // "{"name":"public name"}"
128
+
117
129
// 只能内部访问私有属性
118
130
p .say () // private property
119
131
@@ -122,13 +134,13 @@ console.log('_private' in p) // false
122
134
// 不能遍历到私有属性
123
135
Object .keys (p) // ["name", "say"]
124
136
137
+ // 私有属性不能赋值
125
138
p ._private = ' 000' // Uncaught Error: cannot set property _private
126
139
127
140
```
128
141
129
- 上面代码使用了4个 trap 函数来实现,参数 ` filter ` 函数是用来过滤私有属性的过滤器。` has ` 函数因为在 Proxy 中用来监听对象 ` in ` 的使用,所以成了过滤私有属性的核心。` ownKeys ` 过滤私有属性,让 ` Object.keys(p) ` 返回其他所有属性。
130
142
131
- 注意,因为在 Proxy 上调用方法, ` this ` 默认指向的是 Proxy ,而不是原始对象,因此方法将无法访问私有属性,所以通过将方法绑定到 ` get ` 函数中来解决。
143
+ 注意,因为在 Proxy 上调用方法, ` this ` 默认指向的是 Proxy 代理 ,而不是原始对象,因此方法将无法访问私有属性,所以通过将方法绑定到 ` get ` 函数中来解决。
132
144
133
145
134
146
## 枚举 Enum
@@ -267,12 +279,11 @@ obj.key('x') // undefined
267
279
268
280
## 追踪对象和数组
269
281
270
- 这也是观察者模式的一部分,同时 Vue.js 在今年(2017)也会实现一个基于 Proxy 的 Observation
282
+ 这也是观察者模式的一部分
283
+ 在 Vue.js 中无法监听数组的 ` length ` 导致 ` arr.length = 1 ` 这种数据的改变无法监听,因此 Vue.js 在今年(2017)也会实现一个基于 Proxy 的 Observation
271
284
272
285
当对象或数组发生变化时,我们通过订阅的事件就可以观察到,同理,我们还可以添加验证的拦截,在数据更改之前先做验证处理。
273
286
274
- 在 Vue.js 中无法监听数组的 ` length ` 导致 ` arr.length = 1 ` 这种数据的改变无法监听
275
-
276
287
因此我们把对象和数组也加一层 Proxy 来处理,我们把所有的改变都转发到原对象上,在修改或删除之后添加一个函数当做监听器 :
277
288
278
289
``` js
@@ -407,7 +418,7 @@ p2.value // "proxy value" p1 p2 引用同一个实例对象
407
418
408
419
一旦某个代理对象被撤销,它将变的几乎完全不可用,在它身上执行任何的可代理操作都会抛出 TypeError 异常。
409
420
410
- 所以,利用 ` Proxy.revocable ` 实现一个验证和可撤销访问的例子
421
+ ` Proxy.revocable ` 的一个使用场景是,目标对象不允许直接访问,必须通过代理访问,一旦访问结束,就收回代理权,不允许再次访问。 所以,利用 ` Proxy.revocable ` 实现一个验证和可撤销访问的例子
411
422
412
423
``` js
413
424
const revocableInfo = Proxy .revocable ({}, {
@@ -467,7 +478,7 @@ setUser(revocableInfo.proxy)
467
478
// TypeError: must be "name" or "age"
468
479
469
480
470
- // 代理对象执行撤销方法
481
+ // 代理对象执行撤销方法 收回代理权
471
482
revocableInfo .revoke ()
472
483
setUserAgain ()
473
484
// TypeError: Cannot perform 'set' on a proxy that has been revoked
@@ -477,13 +488,16 @@ setUserAgain()
477
488
某个代理对象一旦被撤销,这个代理对象永远不可能恢复到原来的状态,同时和它关联的目标对象以及处理器对象将有可能被垃圾回收掉。
478
489
479
490
491
+ ## 最后
492
+
493
+ Proxy 是在目标对象之前加一层劫持,外界对该对象的访问,都必须先通过这层劫持,因此提供了一种机制,可以对外界的访问进行过滤和改写,等同于在语言层面做出修改,所以属于一种 『元编程』
480
494
481
- ### 参考文章
495
+ > 参考文章、代码
482
496
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/ )
487
501
488
502
489
503
0 commit comments