流月
  • CSS
  • JavaScript
  • Web API
  • TypeScript
  • 框架

    • React
    • Vue
  • 其他

    • 小程序
    • 工程化
    • 性能优化
    • 测试
    • 其他
  • nodejs
  • deno
  • express
  • nginx
  • docker
  • 其他
  • 安全基础
  • 正则表达式
  • 网络基础
  • 设计模式
  • 数据结构与算法
  • LeetCode
  • CodeWars
  • 手写代码
  • Git
  • devops
  • 编码原则
  • 防御编程
  • Chrome
  • Edge
  • Flutter
  • Linux
  • 库
  • 网站
  • 面试
  • 摘抄
  • 方法论
  • 语法
  • 王小波
  • Elon Musk
  • CSS
  • JavaScript
  • Web API
  • TypeScript
  • 框架

    • React
    • Vue
  • 其他

    • 小程序
    • 工程化
    • 性能优化
    • 测试
    • 其他
  • nodejs
  • deno
  • express
  • nginx
  • docker
  • 其他
  • 安全基础
  • 正则表达式
  • 网络基础
  • 设计模式
  • 数据结构与算法
  • LeetCode
  • CodeWars
  • 手写代码
  • Git
  • devops
  • 编码原则
  • 防御编程
  • Chrome
  • Edge
  • Flutter
  • Linux
  • 库
  • 网站
  • 面试
  • 摘抄
  • 方法论
  • 语法
  • 王小波
  • Elon Musk
  • 设计模式

设计模式

在 JS 中,很多设计模式都是通过闭包和高阶函数实现的。和传统语言的实现不太一样。

前置知识

闭包

高阶函数

满足任一条件

  • 函数作为参数传递
  • 函数作为返回值返回

面向对象的 JavaScript

  • 动态类型和鸭子类型
  • 多态
  • 封装
  • 原型模式和基于原型继承的 JavaScript 对象系统

AOP

面向切面的编程

  • 把一些根核心业务无关的功能抽离出来,包括日志统计、安全控制、异常处理等。

单例模式

单例模式的核心就是确保只有一个实例,并提供给全局访问

var a = {} 就是一个单例模式

不过它暴露了全局变量

使用闭包封装私有变量

var user = (function() {
  var __name = 'seven'
  return {
    getName() {
      return __name
    }
  }
})()

通用的惰性单例

在需要的时候才创建对象实例

var getSingle = function(fn) {
  var ret
  return function() {
    return ret || ret = fn.apply( this, arguments)
  }
}

观察者模式(发布-订阅)

你在 DOM 节点上绑定过事件函数,你就是用过发布-订阅模式

// 随意添加或者删除订阅者
document.body.addEventListener('click', function() { alert(2) },false)
document.body.addEventListener('click', function() { alert(2) },false)
document.body.click()

ES6 实现

class Subject() {
  constuctor() {
    this.observers = []
  }
  add(observer) {
    this.observers.push(observer)
  }
  remove(observer) {
    const index = this.observers.indexOf(observer)
    if (index > -1) {
      this.observers.splice(index, 1)
    }
  }
  trigger() {
    this.observer.forEach(observer => {
      observer.update()
    })
  }
}
class Observer() {}
  constuctor(name) {
    this.name = name
  }
  update() {
    console.log(this.name)
  }

工厂模式

迭代器模式

迭代器就是循环访问聚合对象中的每个元素

所有的集合类型、字符串都有默认迭代器

  • keys()
  • values()
  • entries()

代理模式

缓存代理

缓存代理可以为一下开销大的运行结果提供暂时的存储, 下次如果参数一样,返回前面存储的运算结果。

// 求乘积的函数
var mult = function() {
  var a = 1
  for (var i = 0; l = arguments.length; i < 1; i++) {
    a *= arguments[i]
  }
  return a
}

var proxyMult = (function() {
  var cache = {}
  return function() {
    var args = [].join.call(arguments, ',')
    if (args in cache) {
      return cache[ args ]
    }
    return cache[args] = mult.apply(this, arguments)
  }
})()

proxyMult(1, 2, 3, 4)

适配器模式 Adapter

解决两个软件实体间的接口不兼容的问题

var googleMap = {
  show() {
  }
}
var baiduMap = {
  render() {
  }
}

var renderMap = function( map ) {
  if ( map.show instanceof Function) {
    map.show()
  }
}
var baiduMapAdapter = {
  show() {
    return baiduMap.render()
  }
}

renderMap( googleMap )
renderMap( baiduMapAdapter )
Last Updated: 7/10/20, 1:56 AM
Contributors: wangqi