#原型模式

JavaScript 面向对象系统就是通过原型模式实现的

#以类为中心的语言需要单独实现原型模式

比如 JAVA 中,类才是它面向对象系统的根本。所以说在 JAVA 中,我们可以选择不使用原型模式 —— 所有的实例都必须要从类中来,当我们希望创建两个一模一样的实例时,就只能参数传两遍,非常麻烦

Dog dog = new Dog('旺财', 'male', 3, '柴犬')
Dog dog_copy = new Dog('旺财', 'male', 3, '柴犬')

Java 专门针对原型模式设计了一套接口和方法,在必要的场景下会通过原型方法来应用原型模式

#JavaScript 中的“类”

ES6 的类其实是原型继承的语法糖

#谈原型模式,其实是谈原型范式

原型编程范式的核心思想就是利用实例来描述对象,用实例作为定义对象和继承的基础

JavaScript 中,原型编程范式的体现就是基于原型链的继承

#对象的深拷贝

实现 JavaScript 中的深拷贝,有一种非常取巧的方式 —— JSON.stringify

它存在一些局限性,比如无法处理 function、无法处理正则等等,但是可以对 JSON 对象放心使用

深拷贝没有完美方案,每一种方案都有它的边界 case

function deepClone(obj) {
  // 如果是 值类型 或 null,则直接return
  if (typeof obj !== 'object' || obj === null) {
    return obj
  }

  // 定义结果对象
  let copy = {}

  // 如果对象是数组,则定义结果数组
  if (obj.constructor === Array) {
    copy = []
  }

  // 上方精简为一行
  let copy = new obj.constructor()

  // 遍历对象的key
  for (let key in obj) {
    // 如果key是对象的自有属性
    if (Object.hasOwn(obj, key)) {
      // 递归调用深拷贝方法
      copy[key] = deepClone(obj[key])
    }
  }

  return copy
}

#为什么使用 Object.hasOwn 替换 Object.prototype.hasOwnProperty.call()

  1. 因为 Object.create(null).hasOwnProperty() 会报错
  2. 对象内置属性 hasOwnProperty 可以改写该方法,被使用 JSON 对象恶意赋值会使网站崩溃

#小结

原型模式不仅是设计模式,也是编程范式,是 JS 面向对象的根基