理解 JavaScript 的继承

By bobo 2021-12-21 14:20:38 文章分类:JavaScript

只写了一个寄生式组合继承,其可以算是引用类型继承的最佳模式,注重过程还是能学习到很多知识点。

function Parent(name) {
    this.name = name
}

Parent.prototype.getName = function () {
    return this.name
}

function Child(name, age) {
    // 构造函数继承
    Parent.call(this, name)
    this.age = age
}

/**
 * Object.create() 方法创建一个新对象,使用现有的对象来提供新创建的对象的 __proto__
 *
 * @param proto
 * @param properties
 * @returns {F}
 */
function myObjectCreate(proto, properties) {
    if (typeof proto !== 'object' && proto !== null) {
        throw new TypeError('Object prototype may only be an Object or null')
    }

    function F() {}
    F.prototype = proto
    const f = new F()

    if (proto === null) {
        Object.setPrototypeOf(f, proto)
    }

    const isObject = o => Object.prototype.toString.call(o) === '[object Object]'
    if (isObject(properties)) {
        for (let key in properties) {
            if (Object.prototype.hasOwnProperty.call(properties, key) && !isObject(properties[key])) {
                throw new TypeError('Property description must be an object')
            }
        }
        Object.defineProperties(f, properties)
    }

    return f
}

// 寄生式继承
Child.prototype = myObjectCreate(Parent.prototype, {
    getAge: {
        enumerable: true,
        configurable: true,
        writable: true,
        value: function () {
            return this.age
        }
    },
    like: {
        enumerable: true,
        configurable: true,
        writable: true,
        value: 'coding'
    }
})

Object.defineProperty(Child.prototype, 'constructor', {
    enumerable: false,
    configurable: false,
    writable: false,
    value: Child
})

const c = new Child('bo', 100)

验证一波


// 实例对象的 __proto__ 指向的是创建它的构造函数的 prototype 对象
console.log(Child.__proto__ === Function.prototype) // true
console.log(Child.prototype.__proto__ === Parent.prototype) // true
console.log(Parent.prototype.__proto__ === Object.prototype) // true
console.log(Object.prototype.__proto__ === null) // true