JS 的继承本身是依赖原型的,所以在 JS 中不必刻意把原型模式当做一种设计模式来理解,把它当做一种编程范式理解即可。

# 原型

在 JS 中,每个构造函数都有一个 prototype 属性,这个属性指向构造函数的原型对象,这个原型对象有一个 constructor 属性指回到构造函数。通过这个构造函数生成的实例上会有一个 proto 属性,它指向构造函数的原型对象。

# 原型链

当我们访问一个 JS 实例的属性或方法时,首先会搜索这个实例本身。如果这个当前实例没有对应的属性和方法,会去搜索实例的原型对象,如果原型对象也搜索不到,就会搜索原型对象的原型对象,一直找到 Object.prototype ,如果还找不到就会报错,这样就形成了一条搜索链条,这个链条就是原型链。

下面用一张图来展示下:

注意:Function.prototype 对象是一个函数,而它的原型则是 Object.prototype 即 Function.prototype.__proto__ === Object.prototype ,这样做的原因是为了兼容之前的代码。 。

# 深拷贝

深拷贝最简单的实现方式是通过 JSON.stringify 。

const person = {
    name: 'f',
    age: 18,
    scores: {
        math: 100,
        english: 120
    }
}

const personCopy = JSON.parse(JSON.stringify(person))
personCopy.scores.math = 120

console.log(person.scores.math); // 100
console.log(personCopy.scores.math); // 120

使用这个方法存在着一些局限,比如无法处理function和正则等,传入的参数必须是 JSON 对象形式的。

下面我们来借助递归实现个深拷贝:

function deepClone(obj) {
  if (typeof obj !== 'object' || obj === null) return obj;

  let copy = Array.isArray(obj) ? [] : {}

  for (let key in obj) {
    if (obj.hasOwnProperty(key)) {
      copy[key] = deepClone(obj[key]);
    }
  }

  return copy;
}

扩展资料:

深拷贝的终极探索 (opens new window)

jQuery中的extend方法源码 (opens new window)