JavaScript 设计模式(二)

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

5. 代理模式

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

vue3 还没出来之前,我猜过可能会使用 proxy 取代 defineProperty ,结果也被验证了,毕竟 proxydefineProperty 支持更多的拦截机制,可以对数组的方法进行拦截。

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 {
@readonly
name() {
console.log("huro!!")
}
} const huro = new Person();
huro.eat(); // huro!! // 我想改掉 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));
} 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 设计模式是程序设计中很重要的一个环节,在了解了各种设计模式之后,可以在遇到实际项目的时候,预先选择好一个好的设计模式用于开发,提高项目的可扩展性,也有助于我们理解源码。

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

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

    JavaScript 设计模式(一) 本文需要读者至少拥有基础的 ES6 知识,包括 Proxy, Reflect 以及 Generator 函数等. 至于这次为什么分了两篇文章,有损传统以及标题的正 ...

  2. 一篇文章图文并茂地带你轻松学完 JavaScript 原型和原型链

    JavaScript 原型和原型链 在阅读本文章之前,已经默认你了解了基础的 JavaScript 语法知识,基础的 ES6 语法知识 . 本篇文章旨在为 JavaScript继承 打下基础 原型 在 ...

  3. 一篇文章图文并茂地带你轻松学完 JavaScript 继承

    JavaScript 继承 在阅读本文章之前,已经默认你了解了基础的 JavaScript 语法知识,基础的 ES6 语法知识 . 继承种类 简单的继承种类可以分为 构造函数继承 原型链继承 clas ...

  4. 一篇文章图文并茂地带你轻松学完 JavaScript 事件循环机制(event loop)

    JavaScript 事件循环机制 (event loop) 本篇文章已经默认你有了基础的 ES6 和 javascript语法 知识. 本篇文章比较细致,如果已经对同步异步,单线程等概念比较熟悉的读 ...

  5. 一篇文章图文并茂地带你轻松学完 JavaScript 闭包

    JavaScript 闭包 为了更好地理解 JavaScript 闭包,笔者将先从 JavaScript 执行上下文以及 JavaScript 作用域开始写起,如果读者对这方面已经了解了,可以直接跳过 ...

  6. 一篇文章图文并茂地带你轻松实践 HTML5 history api

    HTML5 history api 前言 由于笔者在网络上没有找到比较好的关于 history api 的实践案例,有的案例过于杂乱,没有重点,有些案例只是告诉读者 api 是什么,却没告诉怎么用,本 ...

  7. 一篇文章图文并茂地带你轻松学会 HTML5 storage

    html5 storage api localStorage 和 sessionStorage 是 html5 新增的用来存储数据的对象,他们让我们可以以键值对的形式存储信息. 为什么要有 stora ...

  8. 一篇文章让你快速入门 学懂Shell脚本

    Shell脚本,就是利用Shell的命令解释的功能,对一个纯文本的文件进行解析,然后执行这些功能,也可以说Shell脚本就是一系列命令的集合. Shell可以直接使用在win/Unix/Linux上面 ...

  9. 学完JavaScript基础有感

    紧接上一篇回来了,这几天一直学js,会不自觉的和其他的编程语言联系在一起,在没有学jQuery之前,结合我所学的c,java,数据结构,数据库以及部分html感觉到JavaScript里面又很多相似的 ...

随机推荐

  1. 【Oracle】密码文件相关

    Oracle数据库的orapwd命令,主要用来建立密码(口令)文件. 一.查看帮助信息 [oracle@oracle11g dbs]$ orapwd Usage: orapwd file=<fn ...

  2. 使用 gRPCurl 调试.NET 5的gPRC服务

    介绍 你用过 Curl 吗?这个工具允许你通过 http 来发送数据,现在有一个适用于gGRPC的工具,gRPCurl,在本文中,我将介绍如何下载安装这个工具,然后通过这个工具调试我们.NET 5上面 ...

  3. 5.2 Spring5源码--Spring AOP源码分析二

    目标: 1. 什么是AOP, 什么是AspectJ 2. 什么是Spring AOP 3. Spring AOP注解版实现原理 4. Spring AOP切面原理解析 一. 认识AOP及其使用 详见博 ...

  4. 小试牛刀ElasticSearch大数据聚合统计

    ElasticSearch相信有不少朋友都了解,即使没有了解过它那相信对ELK也有所认识E即是ElasticSearch.ElasticSearch最开始更多用于检索,作为一搜索的集群产品简单易用绝对 ...

  5. Trino总结

    文章目录 1.Trino与Spark SQL的区别分析 2.Trino与Spark SQL解析过程对比 3.Trino基本概念 4.Trino架构 5.Trino SQL执行流程 6.Trino Ta ...

  6. 1V转5V芯片,三个元件即可组成完整的稳压方案

    1V低电压要转成5V的电压,需要1V转5V的芯片,由于1V输入,所以不需要指望能输出多大的电流,压差和1V的供电电压意味着供电电流也是无法做大的了.一般1V转5V的输出电流在0MA-100mA,一般6 ...

  7. 支持 gRPC 长链接,深度解读 Nacos 2.0 架构设计及新模型

    支持 gRPC 长链接,深度解读 Nacos 2.0 架构设计及新模型 原创 杨翊(席翁) 阿里巴巴云原生 2020-12-28    

  8. vim 查找并替换多个匹配字符

    通常我们在使用vim的使用需要查找文档中是否含有需要的字符 1.vim 1.txt进入文档编辑 2.输入/键,再输入需要查找的字符,或者输入?键再输入需要查找的字符 3.查找到后可以enter进去,再 ...

  9. LOJ10069 TREE

    题目描述 原题来自:2012 年国家集训队互测 给你一个无向带权连通图,每条边是黑色或白色.让你求一棵最小权的恰好有 need 条白色边的生成树.题目保证有解. 输入格式 第一行 V,E,need 分 ...

  10. power network 电网——POJ1459

    Power Network Time Limit: 2000MS   Memory Limit: 32768K Total Submissions: 27282   Accepted: 14179 D ...