JavaScript 设计模式包括以下五个原则:单一职责原则(S)、开放封闭原则(O)、里氏替换原则(L)、接口分离原则(I)和依赖倒置原则(D)。

1. 工厂模式:将对象的创建过程封装在工厂类中,使得客户端不需要关心对象的具体实现。这样可以降低耦合度,提高代码的可维护性。示例代码如下:

```javascript

class CarFactory {

constructor(name) {

this.name = name;

}

productBus() {

console.log(this.name, '生产公交车');

}

productCar() {

console.log(this.name, '生产小汽车');

}

}

class Creator {

constructor(name) {

return new CarFactory(name);

}

}

// 测试

let p = new Creator('汽车工厂');

p.productBus();

p.productCar();

```

应用场景:jQuery、React.createElement 和 Vue.component 都是遵循这些设计原则的例子。

ue.js 中的异步组件示例:

```javascript

Vue.component('async-example', function (resolve, reject) {

setTimeout(() => {

resolve({

template: '

i am async
'

})

}, 1000);

});

```

单例模式示例:

```javascript

class SinglonObject {

login() {

console.log('登录');

}

}

SinglonObject.getInstance = (() => {

let instance;

return () => {

if (!instance) {

instance = new SinglonObject();

}

return instance;

};

})(); // 测试

let login1 = SinglonObject.getInstance();

let login2 = SinglonObject.getInstance();

login1.login();

login2.login();

console.log(login1 === login2);

```

jQuery 的单例模式实现:

```javascript

if (window.jQuery != null) {

return window.jQuery;

} else {

// 初始化

}

```

```javascriptclass LoginDialog {

constructor() {

this.state = 'hide';

}

show() {

if (this.state === "show") {

console.log("登录框已显示");

return;

}

this.state = 'show';

console.log("显示登录框");

}

hide() {

if (this.state === "hide") {

console.log("登录框已隐藏");

return;

}

this.state = 'hide';

console.log("隐藏登录框");

}

}

// 测试

let login1 = LoginDialog.getInstance();

let login2 = LoginDialog.getInstance();

login1.show();

login2.show();

console.log(login2 == login1);

```

```

class Adaptee {

specialRequest() {

return '德国插头';

}

}

class Target {

constructor() {

this.adaptee = new Adaptee();

}

request() {

return `${this.adaptee.specialRequest()}--->中国插头`;

}

}

function createTarget() {

return new Target();

}

let target = createTarget();

let res = target.request(); // "德国插头--->中国插头"

console.log(res); // "德国插头--->中国插头"

```

```javascriptclass Circle {

draw() {

console.log('画一个圆');

}

}

class Decorator {

constructor(circle) {

this.circle = circle;

}

draw() {

this.circle.draw();

this.setRedBorder(this.circle);

}

setRedBorder(circle) {

console.log('给圆设置红色边框');

}

}

let circle = new Circle();

circle.draw();

console.log(circle); // {}

let dec = new Decorator(circle);

dec.draw();

// [Circle] {} // Circle类的原型被添加到了装饰器中,所以在dec中也可以看到Circle类的内容。

function testDec(isDec) {

return target => {

target.isDec = isDec;

};

}

@testDec(true) class Demo {}; // Demo类现在具有isDec属性,值为true。可以通过Demo.isDec获取。

console.log(Demo.isDec); // true

const Foo = { foo() { console.log('foo'); } }; // Foo对象具有foo方法。

@Mixins(Foo) class MyClass {}; // MyClass类继承了Foo对象的所有方法。可以通过new MyClass().foo()调用foo方法。

let obj = new MyClass();

obj.foo(); // 'foo'

function makeImmutable(target) {

return Object.freeze((Object.assign(Object.create(target), target))); // 将目标对象转换为只读对象,使其不可修改。

}

const immutableObj = makeImmutable({ foo: function() {} }); // 在makeImmutable函数中使用Object.create创建了一个新对象,该对象与原始对象共享所有属性,但不是同一个对象。因此,immutableObj可以访问原始对象的属性,但不能直接修改它们。例如,immutableObj.foo()将调用原始对象的属性,而不是重新定义它。如果尝试通过immutableObj来修改属性,则会抛出错误。例如,immutableObj.foo = function() {}将引发TypeError。

```javascript/**

* @desc 只读

* @param {Class} target 目标类

* @param {string} name 属性名

* @param {Object} descriptor 属性描述对象,包含四个值:writable、enumerable、configurable、value

*/

function readonly(target, name, descriptor) {

descriptor.writable = false;

return descriptor;

}

class Person {

constructor() {

this.first = 'a';

this.last = 'b';

}

@readonly

getName() {

return `a: ${this.first}, b: ${this.last}`;

}

}

let people = new Person();

console.log(people.getName()); // people.getName = 'iwen' 修改会报错

import { deprecate } from "core-decorators";

class Person {

@deprecate({ message: '即将废弃', url: 'www.baidu.com' })

getName() {

return "iwen";

}

}

let p = new Person();

console.log(p); // 在不修改 add 方法的前提下打印出参数:Person { first: 'a', last: 'b', getName: [Function] }

```

## 代理模式

客户端与主机无法直接交互,但通过代理可以实现访问。例如,科学上网和公司内部网络的访问。

### RealImg

```javascript

class RealImg {

constructor(fileName) {

this.fileName = fileName;

this.loadFromDisk();

}

loadFromDisk() {

console.log('加载', this.fileName);

}

display() {

console.log('显示', this.fileName);

}

}

```

### ProxyImg

```javascript

class ProxyImg {

constructor(fileName) {

this.realImg = new RealImg(fileName);

}

display() {

this.realImg.display();

}

}

```

使用示例:

```javascript

let proxyImg = new ProxyImg('1.png');

proxyImg.display();

```

```javascript// 明星经纪人

const star = {name: '张xx', age: 18, phone: 'star 16666666666'};

const agent = new Proxy(star, {

get(target, key, val) {

if (key === 'phone') {

return 'agent 15888888888';

}

if (key === 'price') {

return 120000;

}

return target[key];

},

set(target, key, val) {

if (key === 'customPrice') {

if (val < 100000) {

console.log('价格太低');

} else {

target[key] = val;

return;

}

}

}

});

console.log(agent.phone); // agent 15888888888

console.log(agent.price); // 120000

console.log(agent.name); // 张xx

agent.customPrice = 1200;

```

应用场景

## 页面事件绑定

在前端开发中,我们经常需要为页面元素绑定事件处理器。例如,当用户点击按钮时触发某个函数。这时候,我们可以使用事件代理来简化代码。

```javascript

document.getElementById('button').addEventListener('click', function() {

// do something

});

```

## Promise中的then

Promise 是 JavaScript 中用于处理异步操作的一种方式。当我们需要在 Promise 完成后执行一些操作时,可以使用 `then` 方法。

```javascript

const promise = new Promise((resolve, reject) => {

setTimeout(() => {

resolve('success');

}, 1000);

});

promise.then(function(value) {

console.log(value); // 'success'

});

```

## Node中的Event

Node.js 是一个基于 Chrome V8 引擎的 JavaScript 运行环境。在 Node.js 中,我们可以使用 `EventEmitter` 类来处理事件。

```javascript

const EventEmitter = require('events');

class MyEmitter extends EventEmitter {}

const myEmitter = new MyEmitter();

myEmitter.on('event', function() {

console.log('event occurred');

});

myEmitter.emit('event'); // 'event occurred' logged to the console

```

## Vue中的生命周期

在 Vue.js 中,每个组件都有一个生命周期,可以在不同的阶段执行一些操作。例如,在组件创建完成后执行一些初始化操作。

```javascript

new Vue({

el: '#app',

data: {},

created() {

console.log('Component created'); // 'Component created' logged to the console after the component is instantiated

}

});

```

```javascriptclass State {

constructor(color) {

this.color = color;

}

handle(context) {

console.log(`turn to ${this.color} light`);

context.setState(this);

}

}

class Context {

constructor() {

this.state = null;

}

getState() {

return this.state;

}

setState(state) {

this.state = state;

}

}

let context = new Context();

let red = new State('红灯');

let green = new State('绿灯');

let yellow = new State('黄灯');

red.handle(context);

console.log(context.getState()); // State: RedLight

green.handle(context);

console.log(context.getState()); // State: GreenLight

yellow.handle(context);

console.log(context.getState()); // State: YellowLight

```

这段代码是使用javascript-state-machine库实现的状态机。状态机是一种行为模型,它将系统分为一组有限的状态,每个状态都有自己的规则。在这个例子中,状态机有两个状态:收藏和取消收藏。当用户点击一个按钮时,程序会根据当前状态执行相应的操作。如果当前状态是收藏,则执行doStore方法;否则,执行deleteStore方法。这两个方法都会调用updateText函数来更新按钮的文本。

责任链模式

```javascript

class Action {

constructor(name) {

this.name = name;

this.nextAction = null;

}

setNextAction(action) {

this.nextAction = action;

}

handle() {

console.log(`${this.name} 审批`);

if (this.nextAction != null) {

this.nextAction.handle();

}

}

}

let a1 = new Action('组长');

let a2 = new Action('经理');

let a3 = new Action('总监');

a1.setNextAction(a2);

a2.setNextAction(a3);

a1.handle();

```

策略模式

```javascript

function strategy(condition) {

switch (condition) {

case 'A':

return function() { /* ... */ };

case 'B':

return function() { /* ... */ };

case 'C':

return function() { /* ... */ };

}

}

let condition = 'A'; // 或者根据实际需求获取条件值

let strategyFunction = strategy(condition); // 根据条件选择对应的策略函数

strategyFunction(); // 执行策略函数

```

桥接模式是一种结构性模式,将抽象部分与实现部分分离,使它们都可以独立地变化。它是一种对象结构型模式,又称柄体(Handle and body)模式或者接口(Interface)模式 。当一个抽象可能有多个实现时,通常用继承来协调他们。

```javascript// 原型模式实现

const prototype = {

sayName() {

return `${this.first} ${this.last}`;

},

say() {

return 'hello';

},

};

// 基于原型创建x

let x = Object.create(prototype);

x.first = 'a';

x.last = 'b';

console.log(x.sayName()); // a b

console.log(x.say()); // hello

// 基于原型创建y

let y = Object.create(prototype);

y.first = 'c';

y.last = 'd';

console.log(y.sayName()); // c d

console.log(y.say()); // hello

```