关于前端:jsliang-求职系列-45-设计模式系列汇总

5次阅读

共计 13641 个字符,预计需要花费 35 分钟才能阅读完成。

一 目录

不折腾的前端,和咸鱼有什么区别

目录
一 目录
二 前言
三 面向对象
 3.1 封装
 3.2 继承
  3.2.1 ES5 写法
  3.2.2 ES6 写法
 3.3 多态
  3.3.1 ES5 写法
  3.3.2 ES6 写法
四 设计准则
五 工厂模式
 5.1 ES5 写法
 5.2 ES6 写法
 5.3 小结
六 单例模式
 6.1 ES5 写法
 6.2 ES6 写法
七 代理模式和中介者模式
 7.1 代理模式
 7.2 中介者模式
 7.3 小结
八 公布订阅模式
 8.1 观察者模式举例
 8.2 Object.defineProperty 和 Proxy
 8.3 小结
九 参考文献

二 前言

返回目录

设计模式是一门学识,它外面有 22+ 品种的设计模式。

淡淡难过:你只管学,过几个月忘了回来再看看你还懂不懂。

前端面试中,常见的你能够答复的设计模式如下:

设计模式 形容 例子
单例模式 一个类只能结构出一个惟一实例 Redux/Vuex 的 Store
工厂模式 对创建对象逻辑的封装 jQuery 的 $(selector)
观察者模式 当一个对象被批改时,会主动告诉它的依赖对象 Redux 的 subsrcibe、Vue 的双向绑定
装璜器模式 对类的包装,动静地扩大类的性能 React 的高阶组件、ES7 装璜器
适配器模式 兼容新旧接口,对类的包装 封装旧 API
代理模式 管制对象的拜访 事件代理、ES6 的 Proxy

当然,如果你还理解其余,那就更好了~

三 面向对象

返回目录

在开始温习设计模式之前,咱们回顾下面向对象。

什么是面向对象,咱们能够和面向过程比对一下:

  • 面向过程 :关注的是过程中的每一个环节

    • 吃蛋炒饭(独身狗版):买鸡蛋 → 买米 → 蒸米 → 炒蛋 → 炒米 → 混合 → 搅拌 → 蛋炒饭
  • 面向对象 :关注的是让对象做事件

    • 吃蛋炒饭(情侣版):找一个对象,做蛋炒饭,你吃蛋炒饭

事实可能不会扎你的心,然而 jsliang 会。

jsliang 也是独身汪,所以扎你们前先扎了本人,不慌,一起扎心

​面向对象(Object Oriented Programming,简称 OOP),是一种编程开发思维。

它将真实世界各种简单的关系,形象为一个个对象,而后由对象之间的分工与单干,实现对真实世界的模仿。

  1. 事实需要(盖大楼)
  2. 须要哪些对象(设计师、搬运工、砌墙师、木匠、导购…)
  3. 分工与单干
  4. 实现我的项目

这就好比你要实现一个我的项目,你能够会配置 Webpack + Babel,并且用上 React 和 Ant Design。

那么 Webpack 由什么组成呢,你又能够将其拆离开,填充一个一个 loaderplugin,最终由一个个小组件组合成一个我的项目。

简略来说:面向对象关怀的不是过程,关怀的是哪个局部找谁来实现。

面向对象有三大个性: 封装、根底和多态 ,上面咱们一一介绍。

3.1 封装

返回目录

假如咱们须要判断指标类型:

面向过程写法

// 明天 A 找你判断下类型
const A = 'jsliang';
const AType = Object.prototype.toString.call(A);
console.log(AType); // [object String]

// 今天 B 找你判断下类型
const B = 25;
const BType = Object.prototype.toString.call(B);
console.log(BType); // [object Number]

// 先天 C 找你判断下类型
const C = {obj: 'girl'};
const CType = Object.prototype.toString.call(C);
console.log(CType); // [object Object]

这就好比明天亲戚 A 找你办事,今天亲戚 B 找你办事,先天亲戚 C 找你办事,然而他们要你帮忙做的是查一下某某明星。

烦不烦,为啥别家亲戚是介绍相亲,你家亲戚是介绍明星。

于是你想了个法子:

面向对象写法

// 判断类型
const getType = (obj) => Object.prototype.toString.call(obj);

// 明天 A 找你判断下类型
const A = 'jsliang';
console.log(getType(A)); // [object String]

// 今天 B 找你判断下类型
const B = 25;
console.log(getType(B)); // [object Number]

// 先天 C 找你判断下类型
const C = {obj: 'girl'};
console.log(getType(C)); // [object Object]

当你让亲戚用你写的“千度”软件去查找之后,世界霎时宁静了,祝贺你实现了宅男的个性的保护。

咳咳,话回正题,其实这就是封装了。

想必看到这里小伙伴也不会生疏,日常工作中,碰到呈现屡次的代码,个别都会采取封装形式将代码抽取进去。

封装的益处 :封装的劣势在于定义只能够在类外部进行对属性的操作,内部无奈对这些属性指手画脚,要想批改,也只能通过你定义的封装办法。

3.2 继承

返回目录

到职期间,jsliang 每天晚上因为找不到工作而疲乏的时候,都会空想我老爸是千万富翁,其实让我工作只是为了让我能接受考验,最初是要回家继承资产的~

没错,这个继承和你想的继承差不多,就是有一个办法 Father,而后 Children 继承 Father 账目上的内容。

留神是账目上,就是说 Father 的动态属性和静态方法并不会继承,就好比你继承资产就够了,不须要继承父辈的不良嗜好(抽烟喝酒)。

颤抖有益,咱看代码。

3.2.1 ES5 写法

返回目录

ES5 写继承的话,这里来一个手写继承的形式吧,用的是 寄生组合式继承

const Father = function (name, like) {
  this.name = name;
  this.like = like;
  this.money = 10000000;
};

Father.prototype.company = function() {console.log(`${this.name} 有 ${this.money} 元 `);
}

const Children = function (name, like) {Father.call(this);
  this.name = name;
  this.like = like;
}

Children.prototype = Object.create(Father.prototype);
Children.prototype.constructor = Children;

const jsliang = new Children('jsliang', '学习');
console.log(jsliang); // Children {name: "jsliang", like: "学习", money: 10000000}
jsliang.company(); // jsliang 有 10000000 元 

这是一个面试考点,就是考你能不能手写继承。

当然还有其余的继承形式,这是 jsliang 找到的一个较为欠缺的继承办法。

3.2.2 ES6 写法

返回目录

class Father {constructor(name, like) {
    this.name = name;
    this.like = like;
    this.money = 10000000;
  }
  company() {console.log(`${this.name} 有 ${this.money} 元 `);
  }
  // 静态方法并不会继承,并且能够通过类名调用
  static smoke() {console.log(`${this.name} 喜爱抽烟 `);
  }
}

Father.smoke(); // Father 喜爱抽烟

class Children extends Father {constructor(name, like) {super();
    this.name = name;
    this.like = like;
  }
}

const jsliang = new Children('jsliang', '学习');
console.log(jsliang); // Children {name: "jsliang", like: "学习", money: 10000000}
jsliang.company(); // jsliang 有 10000000 元
jsliang.smoke(); // TypeError: jsliang.smoke is not a function

特地揭示 :继承会继承父类的实例属性和实例办法,并不会继承动态属性和静态方法,并且静态方法只能通过类名去调用。

继承的益处 :继承缩小了代码的冗余,省略了很多反复代码,开发者能够从父类底层定义所有子类必须有的属性和办法,以达到耦合的目标;

3.3 多态

返回目录

多态,能够简略了解为继承过去并对其有本人的了解。

多态具体表现为办法重载和办法重写:

  • 办法重载 :重载是指不同的函数应用雷同函数名,然而函数的参数个数或者类型不同。调用的时候依据函数的参数来辨别不同的函数。
  • 办法重写 :重写(也叫笼罩)是指派生类中从新对基类中的虚函数从新实现。即函数名和参数都一样,只是函数的实现体不一样。

上面咱们来个多态之 办法重写 的 ES5 和 ES6 写法。

3.3.1 ES5 写法

返回目录

const Father = function (name, like) {
  this.name = name;
  this.like = like;
  this.money = 10000000;
};

Father.prototype.company = function() {console.log(`${this.name} 有 ${this.money} 元 `);
}

const Children = function (name, like) {Father.call(this);
  this.name = name;
  this.like = like;
  this.money = 10000;
}

Children.prototype = Object.create(Father.prototype);
Children.prototype.constructor = Children;
Children.prototype.company = function() {console.log(`${this.name} 有 ${this.money} 元 `);
}

const father = new Father('jsliang 的老爸', '学习');
console.log(father); // Father {name: 'jsliang 的老爸', like: '学习', money: 10000000}
father.company(); // jsliang 的老爸 有 10000000 元

const jsliang = new Children('jsliang', '学习');
console.log(jsliang); // Children {name: 'jsliang', like: '学习', money: 10000}
jsliang.company(); // jsliang 有 10000 元 

3.3.2 ES6 写法

返回目录

class Father {constructor(name, like) {
    this.name = name;
    this.like = like;
    this.money = 10000000;
  }
  company() {console.log(`${this.name} 有 ${this.money} 元 `);
  }
}

class Children extends Father {constructor(name, like) {super();
    this.name = name;
    this.like = like;
    this.money = 10000;
  }
  company() {console.log(`${this.name} 有 ${this.money} 元 `);
  }
}

const father = new Father('jsliang 的老爸', '抽烟');
console.log(father); // Father {name: 'jsliang 的老爸', like: '抽烟', money: 10000000}
father.company(); // jsliang 的老爸 有 10000000 元

const jsliang = new Children('jsliang', '学习');
console.log(jsliang); // Children {name: 'jsliang', like: '学习', money: 10000}
jsliang.company(); // jsliang 有 10000 元 

果然做“工程师”是没有前途的,做梦才是。

你看要个点赞和 Github star,弹幕评论区全是“下次肯定”。


硬核广告,如果小伙伴须要分割 jsliang,能够到 GitHub 首页找到联系方式:

  • Github

多态的益处 :多态实现了办法的个性化,不同的子类依据具体情况能够实现不同的办法,光有父类定义的办法不够灵便,遇见非凡情况就顾此失彼了。

四 设计准则

返回目录

设计模式有 6 大准则:繁多职责准则、里氏替换准则、依赖倒置准则、接口隔离准则、迪米特准则、凋谢关闭准则。

当然,咱们不是“职业”的,咱们就是面向面试的,所以记住两个准则即可:

  • 繁多职责准则 :一个类只负责一个性能畛域中的相应职责。或者:就一个类而言,只有一个引起它变动的起因。
  • 凋谢关闭准则 :外围的思维是软件实体(类、模块、函数等)是可扩大的、但不可批改的。也就是说,对拓展是凋谢的,对批改是关闭的。

上面咱们开始一一介绍设计模式。

五 工厂模式

返回目录

在日常生活中,咱们晓得有果糖工厂、塑料工厂。

而设计模式中的工厂模式,也是如此。

工厂模式是 JavaScript 中最罕用的一种用于创建对象的设计模式,其外围就是将逻辑封装在一个函数中不裸露创建对象的具体逻辑。

5.1 ES5 写法

返回目录

const Person = function() {const [name, age, sex] = [...arguments];
  this.name = name;
  this.age = age;
  this.sex = sex;
  this.sayName = () => {console.log(` 我叫 ${this.name},性别 ${this.sex},往年 ${this.age}`);
  }
};

const p1 = new Person('jsliang', 25, '男');
const p2 = new Person('靓女', 25, '女');

p1.sayName(); // 我叫 jsliang,性别 男,往年 25
p2.sayName(); // 我叫 靓女,性别 女,往年 25

5.2 ES6 写法

返回目录

class Person {constructor(name, age, sex) {
    this.name = name;
    this.age = age;
    this.sex = sex;
  }
  sayName() {console.log(` 我叫 ${this.name},性别 ${this.sex},往年 ${this.age}`);
  }
}

const p1 = new Person('jsliang', 25, '男');
const p2 = new Person('靓女', 25, '女');

p1.sayName(); // 我叫 jsliang,性别 男,往年 25
p2.sayName(); // 我叫 靓女,性别 女,往年 25

5.3 小结

返回目录

工厂模式是为了解决多个相似对象申明的问题,也就是为了解决实列化对象产生反复的问题。

工厂模式的优缺点如下:

  • 长处 :能解决多个类似的问题。
  • 毛病 :不能晓得对象辨认的问题(对象的类型不晓得)

六 单例模式

返回目录

单例模式即一个类只能结构出惟一实例,单例模式的意义在于共享、惟一,Redux/Vuex 中的 Store、jQuery 的 $ 或者业务场景中的购物车、登录框都是单例模式的利用。

6.1 ES5 写法

返回目录

const Single = function (name, password) {
  this.name = name;
  this.password = password;
};

Single.prototype.login = (name, password) => {if (!this.only) {this.only = new Single(name, password);
  }
  return this.only;
};

let user1 = new Single().login('jsliang', '123456');
let user2 = new Single().login('zhazhaliang', '654321');

console.log(user1 === user2); // true
console.log(user1); // Single {name: 'jsliang', password: '123456'}
console.log(user2); // Single {name: 'jsliang', password: '123456'}

6.2 ES6 写法

返回目录

class SingletonLogin {constructor(name, password) {
    this.name = name;
    this.password = password;
  }
  static getInstance(name, password) {
    // 判断对象是否曾经被创立, 若创立则返回旧对象
    if (!this.instance) {this.instance = new SingletonLogin(name, password);
    }
    return this.instance;
  }
}

let obj1 = SingletonLogin.getInstance('jsliang', '123456')
let obj2 = SingletonLogin.getInstance('zhazhaliang', '654321')

console.log(obj1 === obj2)    // true
console.log(obj1)           // SingletonLogin {name: 'jsliang', password: '123456'}
console.log(obj2)           // SingletonLogin {name: 'jsliang', password: '123456'}

七 代理模式和中介者模式

返回目录

上面咱们将代理模式和中介者模式:

  • 代理模式 :代理模式强调的是个体。将原类(原办法体)进行封装,客户端只须要与代理进行交换,代理就是原类的一个替身。简而言之就是用一个对象代表另外一个对象。
  • 中介模式 :中介模式强调的是相互独立。定义一个中介对象来封装系列对象之间的交互。中介者使各个对象不须要显示地互相援用,从而使其耦合性涣散,而且能够独立地扭转他们之间的交互。

OK,上面咱们通过代码了解下代理模式和中介者模式吧~

7.1 代理模式

返回目录

代码模式就是:

jsliang 要给心动女孩送花,而后 jsliang 不好意思,所以他解脱他的好哥们帮忙送花,这个代理人就是好哥们。

// 心动女孩
const Girl = function() {
  this.name = '心动女孩';
  this.get = (person, gift) => {console.log(`${person} 送给 ${this.name} ${gift}`);
  };
}

// jsliang
const JSLiang = function() {
  this.name = 'jsliang';
  this.send = () => {return '99 朵玫瑰';}
}

// 好哥们
const Friend = function(getUser) {this.getUser = new getUser();
  this.jsliang = new JSLiang();
  this.run = () => {this.getUser.get(this.jsliang.name, this.jsliang.send());
  }
};

// 好哥们帮忙给不同妹子送礼物
const friend = new Friend(Girl);
friend.run(); // jsliang 送给 心动女孩 99 朵玫瑰 

哎,形象全没,jsliang 见一个爱一个,好哥们不得跑断腿,哈哈。

代理模式实用场景

代理模式的实用场景是图片的预加载,在预加载过程中,图片未加载结束之前,用一个 loading 作为图片的占位符,期待加载结束之后再进行赋值。

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width,initial-scale=1.0,maximum-scale=1.0,user-scalable=no">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title> 代理模式 </title>
</head>

<body>
  <div class="animation"> 动画元素 </div>

  <script>
    window.onload = function () {var myImage = (function () {var imgNode = document.createElement("img");
        document.body.appendChild(imgNode);
        return {setSrc: function (src) {imgNode.src = src;}
        }
      })();
      // 代理模式
      var ProxyImage = (function () {var img = new Image();
        img.onload = function () {myImage.setSrc(this.src);
        };
        return {setSrc: function (src) {myImage.setSrc("https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1603709264332&di=f6f8e48c1c88bf640aac9899df98a97c&imgtype=0&src=http%3A%2F%2F5b0988e595225.cdn.sohucs.com%2Fq_mini%2Cc_zoom%2Cw_640%2Fimages%2F20171107%2F643ceb1031394c5887d3509b31878c52.gif");
            setTimeout(() => {img.src = src;}, 3000);
          }
        }
      })();
      // 调用形式
      ProxyImage.setSrc("https://ss1.bdstatic.com/70cFuXSh_Q1YnxGkpoWK1HF6hhy/it/u=3592308877,3684082784&fm=26&gp=0.jpg");
    };
  </script>
</body>

</html>

7.2 中介者模式

返回目录

那么什么是中介者模式呢?

就是当好哥们想赚外快的时候,想起他已经帮 jsliang 跑过腿,那么他也能够帮其他人跑腿啊,于是好哥们变成了中间商,成立了快递公司。

// 心动女孩
const Girl = function() {
  this.name = '心动女孩';
  this.get = (person, gift) => {console.log(`${person} 送给 ${this.name} ${gift}`);
  };
}

// jsliang
const JSLiang = function() {
  this.name = 'jsliang';
  this.send = () => {return '99 朵玫瑰';}
}

// 快递公司
const Express = function(postUser, getUser) {this.postUser = new postUser();
  this.getUser = new getUser();
  this.run = () => {this.getUser.get(this.postUser.name, this.postUser.send());
  }
};

// 快递员
const courier = new Express(JSLiang, Girl);
courier.run(); // jsliang 送给 心动女孩 99 朵玫瑰 

很简略嘛,假如 jsliang 喜爱的女孩不在广州,那么就须要他人“帮忙”将礼物送给异地 girl。

而这种模式,就是中介者模式,作为一个中间人传递信息。

从中能够看出代理模式的益处:

  1. 代理对象能够代替本体被实例化,并使其能够被近程拜访
  2. 能够把本体实例化推延到真正须要的时候。

当然,有好就有坏,在代码中应用代理模式,这个中介会承当较多的责任,一旦中介(快递员)病了,那么你的花就送达不了了。

同样,事实中,如果你真喜爱那妹子,还是当面去送吧,没听过“每天收到花的女孩最初和快递员结婚了么!”

中介者模式实用场景

var goods = {
  // 手机库存
  "red|32G": 3,
  "red|64G": 1,
  "blue|32G": 7,
  "blue|32G": 6,
};

// 中介者
var mediator = (function () {var colorSelect = document.getElementById("colorSelect");
  var memorySelect = document.getElementById("memorySelect");
  var numSelect = document.getElementById("numSelect");
  return {changed: function (obj) {switch (obj) {
        case colorSelect:
          // TODO
          break;
        case memorySelect:
          // TODO
          break;
        case numSelect:
          // TODO
          break;
      }
    },
  };
})();
colorSelect.onchange = function () {mediator.changed(this);
};
memorySelect.onchange = function () {mediator.changed(this);
};
numSelect.onchange = function () {mediator.changed(this);
};

7.3 小结

返回目录

这里将代理模式和中介者模式放在一块,置信小伙伴们也看到了,是有缘故的。

然而理论工作中会不会罕用代理模式和中介者模式,jsliang 不晓得,因为真没试过,可能某些场景试过,然而不会往这方面想。

当前工作有机会再注意注意吧,至于面试中有没可能问?这里也不晓得,因为这是非热点,小伙伴们理解理解即可~

八 公布订阅模式

返回目录

公布 - 订阅模式又叫观察者模式,它定义了对象间的一种一对多的关系,让多个观察者对象同时监听某一个主题对象,当一个对象产生扭转时,所有依赖于它的对象都将失去告诉。

看完定义有点懵?

现实生活中的公布 - 订阅模式,就好比 jsliang 在网上看中一双鞋子,然而没货了,于是点击(订阅)了卖家的发货告诉。等卖家有货之后,所有点击(订阅)了发货告诉的买家,都会看到告诉。

公布 - 订阅模式的优缺点:

  • 长处
  1. 反对简略的播送通信。当对象状态产生扭转时,会主动告诉曾经订阅过的对象,例如下面的举例。
  2. 发布者与订阅者的耦合性升高。我是卖家我并不关怀有多少人订阅了,我只有到货的时候,将货物数量更改下就行了。
  • 毛病
  1. 耗时耗内存。创立订阅者须要耗费肯定的工夫和内存
  2. 适度应用不好保护。

OK,说了那么多,咱们举个代码小例子,而后讲讲 Vue 中的 Object.definePropertyProxy 应用。

8.1 观察者模式举例

返回目录

// 定义发布者
const seller = {};

// 缓存列表:寄存订阅者的回调函数
seller.buyerList = [];

// 订阅办法
seller.listen = (user, fn) => {
  // 如果有人订阅了,那就将它寄存到缓存列表中
  seller.buyerList.push(fn);
  console.log(` 敬爱的 ${user},你曾经订阅了新鞋公布 `);
}

// 公布信息
seller.trigger = () => {
  const buyerList = seller.buyerList;
  for (let i in buyerList) {if (buyerList.hasOwnProperty(i)) {buyerList[i].call(this);
    }
  }
}

const buyer1 = seller.listen('jsliang', () => console.log('色彩是彩色,尺码是 43 码')); // 敬爱的 jsliang,你曾经订阅了新鞋公布
const buyer2 = seller.listen('zhazhaliang', () => console.log('色彩是红色,尺码是 44 码')); // 敬爱的 zhazhaliang,你曾经订阅了新鞋公布

// 假如 2 秒后到货
setTimeout(() => {seller.trigger();
}, 2000);

// 色彩是彩色,尺码是 43 码
// 色彩是红色,尺码是 44 码 

这样就实现了简略的公布 - 订阅模式,如果卖家有不同商品,两个用户别离关注两个不同商品要怎么实现呢?小伙伴们能够思考思考。

8.2 Object.defineProperty 和 Proxy

返回目录

在 Vue 2.0 版本,咱们通过 Object.defineProperty 来察看数据:

const person = {
  name: 'jsliang',
  age: 25,
};

Object.keys(person).forEach((key) => {
  Object.defineProperty(person, key, {
    enumerable: true,
    configurable: true,
    get: () => {console.log('get');
    },
    set: (newName) => {console.log(newName);
    },
  });
});

person.name = 'zhazhaliang'; // zhazhaliang
console.log(person); // {name: [Getter/Setter], age: [Getter/Setter] }

其中:

  • enumerable:对象属性是否可通过 for-in 循环,false 为不可循环,默认值为 true
  • configurable:是否应用 ·、是否需改属性个性、或是否批改拜访器属性,false 为不可从新定义,默认值为 true

那么,咱们再来看看 Proxy

const queuedObserver = new Set();

const observe = fn => queuedObserver.add(fn);
const observeable = obj => new Proxy(obj, {set});

const set = function(target, key, value, receiver) {const result = Reflect.set(target, key, value, receiver);
  queuedObserver.forEach(observer => observer());
  return result;
};

const person = observeable({
  name: 'jsliang',
  age: 25,
});

const print = () => {console.log(` 姓名:${person.name},年龄:${person.age}`);
}
observe(print);

person.name = 'zhazhaliang'; // 姓名:zhazhaliang,年龄:25

那么,为什么 Vue 3.0 要换成 Proxy 呢?

留神听讲,这是面试题~

Object.defineProperty 毛病:

  1. 不能监听数组变动
  2. 必须遍历对象每个属性

Proxy 的指标是对象,这样就省去了属性的遍历。

至于更深刻的理解,譬如如何在页面中敲一个,让页面和数据绑定,这里就不颤抖了,感兴趣的小伙伴们能够看 jsliang 另一个库:

  • all-for-one 你感兴趣的这里全都有

8.3 小结

返回目录

须要斧正一点的是,ES6 Proxy 在模式上属于代理模式。

日常工作中,常见的观察者模式有:

  • Promise
  • Node 的 EventEmitter 事件监听器
  • Vue 的 Watch 申明周期钩子

九 参考文献

返回目录

本系列参考 14 篇文章。

  • [x] 设计模式【浏览倡议:1h】
  • [x] Javascript 罕用的设计模式详解【浏览倡议:1h】
  • [x] JavaScript 设计模式【浏览倡议:20min】
  • [x] JavaScript 中常见设计模式整顿【浏览倡议:1h】
  • [x] JavaScript 常见设计模式解析【浏览倡议:20min】
  • [x] 深刻 JavaScript 设计模式,从此有了优化代码的理论依据【浏览倡议:30min】
  • [x] 设计模式之美 - 前端【浏览倡议:1h】
  • [x] 公布订阅模式,在工作中它的能量超乎你的设想【浏览倡议:30min】
  • [x] 应用原生 JavaScript 构建状态管理系统【浏览倡议:20min】
  • [x] 外观模式、代理模式和中介者模式的区别【浏览倡议:1min】
  • [x]【设计模式】外观模式 & 代理模式 & 中介者模式的区别【浏览倡议:3min】
  • [x] Proxy 与 Object.defineProperty 介绍与比照【浏览倡议:10min】
  • [x] Proxy 和 defineProperty 实现数据察看(观察者模式)【浏览倡议:20min】
  • [x] Proxy 观察者模式以及 Object.defineProperty 的毛病【浏览倡议:3min】

jsliang 的文档库由 梁峻荣 采纳 常识共享 署名 - 非商业性应用 - 雷同形式共享 4.0 国内 许可协定 进行许可。<br/> 基于 https://github.com/LiangJunrong/document-library 上的作品创作。<br/> 本许可协定受权之外的应用权限能够从 https://creativecommons.org/licenses/by-nc-sa/2.5/cn/ 处取得。

正文完
 0