Skip to content
On this page

原型模式

原型模式不仅是一种设计模式,它还是一种编程范式(programming paradigm),是 JavaScript 面向对象系统实现的根基。 在 JavaScript 中,我们使用原型模式,并不是为了得到一个副本,而是为了得到与构造函数(类)相对应的类型的实例、实现数据/方法的共享。克隆是实现这个目的的方法,但克隆本身并不是我们的目的。

原型

在 JavaScript 中,每个构造函数都拥有一个prototype属性,它指向构造函数的原型对象,这个原型对象中有一个 constructor 属性指回构造函数;每个实例都有一个__proto__属性,当我们使用构造函数去创建实例时,实例的__proto__属性就会指向构造函数的原型对象。 具体来说,当我们这样使用构造函数创建一个对象时:

javascript
function User(name, age) {
  this.name = name;
  this.age = age;
}

User.prototype.speak = function() {
  console.log('说中国话')
}

const user = new User('Mondo', 30)

原型链

在上面基础上调用方法

javascript
user.speak(); // 说中国话

console.log(user.toString()) // [object Object]

明明没有定义方法,却可以调用成功。这是因为在访问一个 JS 对象或属性时,首先会查找实例自身,当自身没有找到的时候,会在实例的原型对象上去查找,如果还没有查找到,会继续在原型对象的原型对象上去查找,一直查找到 null,这一条查找轨迹就是原型链。

深拷贝

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

javascript
function deepClone(obj) {
    // 如果是 值类型 或 null,则直接return
    if(typeof obj !== 'object' || obj === null) {
        return obj
    }
    
    // 定义结果对象
    let copy = {}
    
    // 如果对象是数组,则定义结果数组
    if(obj.constructor === Array) {
        copy = []
    }
    
    // 遍历对象的key
    for(let key in obj) {
        // 如果key是对象的自有属性
        if(obj.hasOwnProperty(key)) {
            // 递归调用深拷贝方法
            copy[key] = deepClone(obj[key])
        }
    }
    
    return copy
}

调用深拷贝方法,若属性为值类型,则直接返回;若属性为引用类型,则递归遍历。这就是我们在解这一类题时的核心的方法。