mirror of
https://github.com/ruanyf/es6tutorial.git
synced 2025-05-24 10:22:23 +00:00
docs(proxy): add proxy 实现观察者模式
This commit is contained in:
parent
ba0744a7a4
commit
ff35ad8399
@ -1036,3 +1036,43 @@ Reflect.defineProperty(obj, name, desc);
|
|||||||
```
|
```
|
||||||
|
|
||||||
上面代码中,`Reflect.defineProperty`方法的作用与`Object.defineProperty`是一样的,都是为对象定义一个属性。但是,`Reflect.defineProperty`方法失败时,不会抛出错误,只会返回`false`。
|
上面代码中,`Reflect.defineProperty`方法的作用与`Object.defineProperty`是一样的,都是为对象定义一个属性。但是,`Reflect.defineProperty`方法失败时,不会抛出错误,只会返回`false`。
|
||||||
|
|
||||||
|
## 实例:使用 Proxy 实现观察者模式
|
||||||
|
|
||||||
|
观察者模式(Observer mode)指的是函数自动观察数据对象,一旦对象有变化,函数就会自动执行。
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
const person = observable({
|
||||||
|
name: '张三',
|
||||||
|
age: 20
|
||||||
|
});
|
||||||
|
|
||||||
|
function print() {
|
||||||
|
console.log(`${person.name}, ${person.age}`)
|
||||||
|
}
|
||||||
|
|
||||||
|
observe(print);
|
||||||
|
person.name = '李四';
|
||||||
|
// 输出
|
||||||
|
// 李四, 20
|
||||||
|
```
|
||||||
|
|
||||||
|
上面代码中,数据对象`person`是观察目标,函数`print`是观察者。一旦数据对象发生变化,`print`就会自动执行。
|
||||||
|
|
||||||
|
下面,使用 Proxy 写一个观察者模式的最简单实现,即实现`observable`和`observe`这两个函数。思路是`observable`函数返回一个原始对象的 Proxy 代理,拦截赋值操作,触发充当观察者的各个函数。
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
const queuedObservers = new Set();
|
||||||
|
|
||||||
|
const observe = fn => queuedObservers.add(fn);
|
||||||
|
const observable = obj => new Proxy(obj, {set});
|
||||||
|
|
||||||
|
function set(target, key, value, receiver) {
|
||||||
|
const result = Reflect.set(target, key, value, receiver);
|
||||||
|
queuedObservers.forEach(observer => observer());
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
上面代码中,先定义了一个`Set`集合,所有观察者函数都放进这个集合。然后,`observable`函数返回原始对象的代理,拦截赋值操作。拦截函数`set`之中,会自动执行所有观察者。
|
||||||
|
|
||||||
|
@ -94,20 +94,6 @@
|
|||||||
- Axel Rauschmayer, [ES proposal: Object.getOwnPropertyDescriptors()](http://www.2ality.com/2016/02/object-getownpropertydescriptors.html)
|
- Axel Rauschmayer, [ES proposal: Object.getOwnPropertyDescriptors()](http://www.2ality.com/2016/02/object-getownpropertydescriptors.html)
|
||||||
- TC39, [Object.getOwnPropertyDescriptors Proposal](https://github.com/tc39/proposal-object-getownpropertydescriptors)
|
- TC39, [Object.getOwnPropertyDescriptors Proposal](https://github.com/tc39/proposal-object-getownpropertydescriptors)
|
||||||
|
|
||||||
## Proxy和Reflect
|
|
||||||
|
|
||||||
- Nicholas C. Zakas, [Creating defensive objects with ES6 proxies](http://www.nczonline.net/blog/2014/04/22/creating-defensive-objects-with-es6-proxies/)
|
|
||||||
- Axel Rauschmayer, [Meta programming with ECMAScript 6 proxies](http://www.2ality.com/2014/12/es6-proxies.html): Proxy详解
|
|
||||||
- Daniel Zautner, [Meta-programming JavaScript Using Proxies](http://dzautner.com/meta-programming-javascript-using-proxies/): 使用Proxy实现元编程
|
|
||||||
- Tom Van Cutsem, [Harmony-reflect](https://github.com/tvcutsem/harmony-reflect/wiki): Reflect对象的设计目的
|
|
||||||
- Tom Van Cutsem, [Proxy Traps](https://github.com/tvcutsem/harmony-reflect/blob/master/doc/traps.md):Proxy拦截操作一览
|
|
||||||
- Tom Van Cutsem, [Reflect API](https://github.com/tvcutsem/harmony-reflect/blob/master/doc/api.md)
|
|
||||||
- Tom Van Cutsem, [Proxy Handler API](https://github.com/tvcutsem/harmony-reflect/blob/master/doc/handler_api.md)
|
|
||||||
- Nicolas Bevacqua, [ES6 Proxies in Depth](http://ponyfoo.com/articles/es6-proxies-in-depth)
|
|
||||||
- Nicolas Bevacqua, [ES6 Proxy Traps in Depth](http://ponyfoo.com/articles/es6-proxy-traps-in-depth)
|
|
||||||
- Nicolas Bevacqua, [More ES6 Proxy Traps in Depth](http://ponyfoo.com/articles/more-es6-proxy-traps-in-depth)
|
|
||||||
- Axel Rauschmayer, [Pitfall: not all objects can be wrapped transparently by proxies](http://www.2ality.com/2016/11/proxying-builtins.html)
|
|
||||||
|
|
||||||
## Symbol
|
## Symbol
|
||||||
|
|
||||||
- Axel Rauschmayer, [Symbols in ECMAScript 6](http://www.2ality.com/2014/12/es6-symbols.html): Symbol简介
|
- Axel Rauschmayer, [Symbols in ECMAScript 6](http://www.2ality.com/2014/12/es6-symbols.html): Symbol简介
|
||||||
@ -126,6 +112,21 @@
|
|||||||
- Jason Orendorff, [ES6 In Depth: Collections](https://hacks.mozilla.org/2015/06/es6-in-depth-collections/):Set和Map结构的设计思想
|
- Jason Orendorff, [ES6 In Depth: Collections](https://hacks.mozilla.org/2015/06/es6-in-depth-collections/):Set和Map结构的设计思想
|
||||||
- Axel Rauschmayer, [Converting ES6 Maps to and from JSON](http://www.2ality.com/2015/08/es6-map-json.html): 如何将Map与其他数据结构互相转换
|
- Axel Rauschmayer, [Converting ES6 Maps to and from JSON](http://www.2ality.com/2015/08/es6-map-json.html): 如何将Map与其他数据结构互相转换
|
||||||
|
|
||||||
|
## Proxy和Reflect
|
||||||
|
|
||||||
|
- Nicholas C. Zakas, [Creating defensive objects with ES6 proxies](http://www.nczonline.net/blog/2014/04/22/creating-defensive-objects-with-es6-proxies/)
|
||||||
|
- Axel Rauschmayer, [Meta programming with ECMAScript 6 proxies](http://www.2ality.com/2014/12/es6-proxies.html): Proxy详解
|
||||||
|
- Daniel Zautner, [Meta-programming JavaScript Using Proxies](http://dzautner.com/meta-programming-javascript-using-proxies/): 使用Proxy实现元编程
|
||||||
|
- Tom Van Cutsem, [Harmony-reflect](https://github.com/tvcutsem/harmony-reflect/wiki): Reflect对象的设计目的
|
||||||
|
- Tom Van Cutsem, [Proxy Traps](https://github.com/tvcutsem/harmony-reflect/blob/master/doc/traps.md): Proxy拦截操作一览
|
||||||
|
- Tom Van Cutsem, [Reflect API](https://github.com/tvcutsem/harmony-reflect/blob/master/doc/api.md)
|
||||||
|
- Tom Van Cutsem, [Proxy Handler API](https://github.com/tvcutsem/harmony-reflect/blob/master/doc/handler_api.md)
|
||||||
|
- Nicolas Bevacqua, [ES6 Proxies in Depth](http://ponyfoo.com/articles/es6-proxies-in-depth)
|
||||||
|
- Nicolas Bevacqua, [ES6 Proxy Traps in Depth](http://ponyfoo.com/articles/es6-proxy-traps-in-depth)
|
||||||
|
- Nicolas Bevacqua, [More ES6 Proxy Traps in Depth](http://ponyfoo.com/articles/more-es6-proxy-traps-in-depth)
|
||||||
|
- Axel Rauschmayer, [Pitfall: not all objects can be wrapped transparently by proxies](http://www.2ality.com/2016/11/proxying-builtins.html)
|
||||||
|
- Bertalan Miklos, [Writing a JavaScript Framework - Data Binding with ES6 Proxies](https://blog.risingstack.com/writing-a-javascript-framework-data-binding-es6-proxy/): 使用 Proxy 实现观察者模式
|
||||||
|
|
||||||
## Iterator
|
## Iterator
|
||||||
|
|
||||||
- Mozilla Developer Network, [Iterators and generators](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Iterators_and_Generators)
|
- Mozilla Developer Network, [Iterators and generators](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Iterators_and_Generators)
|
||||||
|
@ -41,7 +41,9 @@ if(true) {
|
|||||||
|
|
||||||
**(2)全局常量和线程安全**
|
**(2)全局常量和线程安全**
|
||||||
|
|
||||||
在`let`和`const`之间,建议优先使用`const`,尤其是在全局环境,不应该设置变量,只应设置常量。这符合函数式编程思想,有利于将来的分布式运算。
|
在`let`和`const`之间,建议优先使用`const`,尤其是在全局环境,不应该设置变量,只应设置常量。
|
||||||
|
|
||||||
|
`const`优于`let`有几个原因。一个是`const`可以提醒阅读程序的人,这个变量不应该改变;另一个是`const`比较符合函数式编程思想,运算不改变值,只是新建值,而且这样也有利于将来的分布式运算;最后一个原因是 JavaScript 编译器会对`const`进行优化,所以多使用`const`,有利于提供程序的运行效率,也就是说`let`和`const`的本质区别,其实是编译器内部的处理不同。
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
// bad
|
// bad
|
||||||
|
@ -16,8 +16,8 @@
|
|||||||
1. [函数的扩展](#docs/function)
|
1. [函数的扩展](#docs/function)
|
||||||
1. [对象的扩展](#docs/object)
|
1. [对象的扩展](#docs/object)
|
||||||
1. [Symbol](#docs/symbol)
|
1. [Symbol](#docs/symbol)
|
||||||
1. [Proxy和Reflect](#docs/proxy)
|
|
||||||
1. [Set和Map数据结构](#docs/set-map)
|
1. [Set和Map数据结构](#docs/set-map)
|
||||||
|
1. [Proxy和Reflect](#docs/proxy)
|
||||||
1. [Iterator和for...of循环](#docs/iterator)
|
1. [Iterator和for...of循环](#docs/iterator)
|
||||||
1. [Generator函数](#docs/generator)
|
1. [Generator函数](#docs/generator)
|
||||||
1. [Promise对象](#docs/promise)
|
1. [Promise对象](#docs/promise)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user