AI智能
改变未来

一篇文章图文并茂地带你轻松学完 JavaScript 设计模式(二)


JavaScript 设计模式(二)

本篇文章是

JavaScript

设计模式的第二篇文章,如果没有看过我上篇文章的读者,可以先看完 上篇文章 后再看这篇文章,当然两篇文章并没有过多的依赖性。

5. 代理模式

代理模式提供了对目标对象的另一种访问机制。

vue3

还没出来之前,我猜过可能会使用

proxy

取代

defineProperty

,结果也被验证了,毕竟

proxy

defineProperty

支持更多的拦截机制,可以对数组的方法进行拦截。

const obj = {};const proxyObj = new Proxy(obj, {set(target, prop, value, receiver) {console.log(\"set:\", prop, \"=\", value);Reflect.set(target, prop, value, receiver);},});proxyObj.a = 1

上述代码是用一个拦截器

Proxy

作代理,使得每次在改变属性的时候,都能打印相应的日记,实际上如果

set

内部改成

render

函数,就可以做到数据改变的时候,渲染页面了。

6. 迭代器模式

迭代器模式能让我们不用在意数据真实的存储结构,更好的获取数据。

下面是一个迭代器模式的例子。

实际上由于原生的

JavaScript

不支持对象进入

for of

循环,原因是因为对象没有一个关于迭代器的

Symbol

属性。

如果要支持的话,可以用下面的做法。

function* gen(obj) {const keys = Object.keys(obj);for (let i = 0; i < keys.length; i++) {const key = keys[i];yield [key, obj[key]];}return;}const obj = {a: 1,b: 2,c: 3,};for (let [key, value] of gen(obj)) {console.log(key, value);}// or// obj[Symbol.iterator] = gen.bind(this, obj);// for (let [key, value] of obj) {//   console.log(key, value);//}

Generator

函数返回一个 迭代器用于迭代,而

for of

循环利用的就是这个迭代器。

7. 装饰器模式

ES7

语法提案中,尚未正式确定,因此主流浏览器都暂时不支持,但是有

babel

啊,这个神奇的工具可以帮助我们将

esnext

转化为浏览器可以执行的代码。

bebel

的官网上可以转化

decorators

const mixins = (...prototype) => {return (target) => {Object.assign(target.prototype, ...prototype);}}const readonly = (target, name, descriptor) => {descriptor.writable = false;return descriptor;}const prototype = {eat() {console.log(\"huro eat!\")}}@mixins(prototype)class Person {@readonlyname() {console.log(\"huro!!\")}}const huro = new Person();huro.eat(); // huro!!//56c我想改掉 huro 这个名字huro.name = () => {console.log(\"xxx\");}// 修改无效huro.name() // huro!!

利用装饰器模式,可以简化代码开发,很重要的一点是,装饰器也可以很好的起到注释的作用。

8. 状态模式

实际上

Promise

的实现中就用到了状态模式,当然也用到了观察者模式,关于

Promise

原理这块,给出简单的实现。并不遵循

Promise/A+

规范。

关于以下代码的一步一步实现,可以参考知乎的一篇文章 图解 Promise 实现原理(一)—— 基础实现

enum Status {Pending = \"Pending\",Resolved = \"Fulfilled\",Rejected = \"Rejected\",}type PromiseFnType = (resolve: (data: any) => any,reject: (error: any) => any) => any;interface Callback {onResolved: (data: any) => any;onRejected: (error: any) => any;resolve: (data: any) => any;reject: (error: any) => any;}class MyPromise {status: Status;value: any;callbacks: Callback[];constructor(fn: PromiseFnType) {this.status = Status.Pending;this.callbacks = [];this.value = null;fn(this.resolve.bind(this), this.reject.bind(this));1044}then(onResolved?: (data: any) => any, onRejected?: (error: any) => any) {return new MyPromise((resolve, reject) => {this.handle({onResolved,onRejected,resolve,reject,});});}handle(callback: Callback) {const { onRejected, onResolved, reject, resolve } = callback;if (this.status === Status.Pending) {this.callbacks.push(callback);return;}if (this.status === Status.Rejected) {let error = this.value;if (onRejected) error = onRejected(error);reject(error);}if (this.status === Status.Resolved && onResolved) {let value = this.value;if (onResolved) value = onResolved(value);resolve(value);}}reject(error: any) {this.value = error;this.status = Status.Rejected;this.callbacks.forEach((cb) => {this.handle(cb);});}resolve(value: any) {if (value instanceof MyPromise) {const then = value.then;then.call(value, this.resolve.bind(this), this.reject.bind(this));return;}this.value = value;this.status = Status.Resolved;this.callbacks.forEach((cb) => {this.handle(cb);});}}new MyPromise((resolve, reject) => {resolve(1);}).then((data) => {return new MyPromise((resolve, reject) => {resolve(data * 2);});}).then((data) => {console.log(data);});

总结

JavaScript

设计模式是程序设计中很重要的一个环节,在了解了各种设计模式之后,可以在遇到实际项目的时候,预先选择好一个好的设计模式用于开发,提高项目的可扩展性,也有助于我们理解源码。

赞(0) 打赏
未经允许不得转载:爱站程序员基地 » 一篇文章图文并茂地带你轻松学完 JavaScript 设计模式(二)