后代互相重叠

我创建了两个对象(Inherits),都从Base继承。 第二个对象的属性分配将覆盖第一个对象中的值。

有什么想法吗? 如何进行适当的继承,以便Base类将包含其继承后代的通用成员,但后代可以分配自己的值而不会相互干扰。

var testParams1 = { title: "john" };
var testParams2 = { title: "mike" };

Function.prototype.inheritsFrom = function (baseClass)
{
    this.prototype = new baseClass;
    this.prototype.constructor = this;
    this.prototype.base = baseClass.prototype;
    return this;
};

function Base() {
    this.viewModel = {};
    this.viewModel.title = (function ()
    {
        var savedVal = "";
        return function (newVal)
        {
            if (typeof (newVal) === "undefined")
            {
                return savedVal;
            }
            savedVal = newVal;
        };
    })();
}
function Inherits(params) {
    this.viewModel.title(params.title);
}

Inherits.inheritsFrom(Base);

///// preparing code:
var testObj1 = new Inherits(testParams1);
var testObj2 = new Inherits(testParams2);

///// testing code:
equals(testObj1.viewModel.title(), testParams1.title, "first instance ok"); // returns "john"
equals(testObj2.viewModel.title(), testParams2.title, "second instance ok");  // also returns "john"

问题)

  • Base类的构造函数只被调用一次。
    this.prototype = new baseClass;
  • 特权方法将参照同this对象跨实例,因为这些方法在构造函数(这被称为只有一次)中创建的。
  • 基于意见问题的问题

  • 如果您计划与不属于您的JavaScript一起工作,您应该尽量避免修改原生原型(即Function.prototype )。
  • 为每个创建的新实例调用构造函数和父构造函数。
  • 继承父原型链(不是父类的实例)。
  • 保持创建的实例数量与原型链中构造函数的调用次数的1:1比率。
  • Max的问题​​的最终解决方案

    请特别注意inherits函数和ParentClass.call(this, title); 线。 要查找的构造函数是ParentClassChildClass

    /**
     * Allows a child constructor to safely inherit the parent constructors prototype chain.
     * @type {Function}
     * @param {!Function} childConstructor
     * @param {!Function} parentConstructor
     */
    function inherits(childConstructor, parentConstructor){
        var TempConstructor = function(){};
        TempConstructor.prototype = parentConstructor.prototype; // Inherit parent prototype chain
    
        childConstructor.prototype = new TempConstructor(); // Create buffer object to prevent assignments directly to parent prototype reference.
        childConstructor.prototype.constructor = childConstructor; // Reset the constructor property back the the child constructor
    };
    
    //////////////////////////////////////
    /** @constructor */
    function ParentClass(title) {
        this.setTitle(title);
    
        var randId_ = Math.random();
        /** @return {number} */
        this.getPrivlegedRandId = function()
            {return randId_;};
    };
    
    /** @return {string} */
    ParentClass.prototype.getTitle = function()
        {return this.title_;};
    
    /** @param {string} value */
    ParentClass.prototype.setTitle = function(value)
        {this.title_ = value;};
    
    //////////////////////////////////////    
    /**
     * @constructor
     * @param {string} title
     * @param {string} name 
     */
    ChildClass = function (name, title) {
        ParentClass.call(this, title); // Call the parent class constructor with the required arguments
    
        this.setName(name);
    }
    inherits(ChildClass, ParentClass); // Inherit the parent class prototype chain.
    
    /** @return {string} */
    ChildClass.prototype.getName = function()
        {return this.name_;};
    
     /** @param {string} value */
    ChildClass.prototype.setName = function(value)
        {this.name_ = value;};
    

    放下兔子洞

    对于那些想知道为什么这么做的人,简单地记住它的inherits功能。

    如何使用原型链解决属性问题

    当在实例级别找不到属性时,JavaScript将尝试通过搜索实例构造函数原型链来解决缺失的属性。 如果在第一个原型对象中找不到该属性,它将搜索父级原型对象,直到Object.prototype 。 如果在Object.prototype找不到它,则会抛出错误。

    从子构造函数调用父构造函数:尝试#1

    // Bad
    var ChildConstructor = function(arg1, arg2, arg3){
        var that = new ParentConstructor(this, arg1, arg2, arg3);
        that.getArg1 = function(){return arg1};
        return that;
    }
    

    使用new ChildConstructor创建的任何变量都将返回ParentConstructor的实例。 ChildConstructor.prototype将不会被使用。

    从子构造函数调用父构造函数:尝试#2

    // Good
    var ChildConstructor = function(arg1, arg2, arg3){
        ParentConstructor.call(this, arg1, arg2, arg3);
    }
    

    现在构造函数和父构造函数被适当调用。 但是,只有在构造函数中定义的方法才会存在。 父原型上的属性将不会被使用,因为它们尚未链接到子构造函数原型。

    继承父级原型:尝试#1

    // Bad
    ChildConstructor.prototype = new ParentConstructor();
    

    取决于是否使用ParentConstructor.call(this) ,父构造函数将被调用一次或多次。

    继承父原型尝试#2

    // Bad
    ChildConstructor.prototype = ParentConstructor.prototype;
    

    尽管这在技术上是有效的,但对ChildConstructor.prototype任何分配也将被分配给ParentConstructor.prototype因为对象是通过引用传递而不是通过复制传递的。

    继承父级原型尝试#3

    // Almost there
    var TempConstructor = function(){};
    TempConstructor.prototype = ParentConstructor.prototype;
    ChildConstructor.prototype = new TempConstructor();
    

    这允许您将属性分配给ChildConstructor.prototype因为它是临时匿名函数的一个实例。 在TempConstructor的实例上TempConstructor将检查它的属性的原型链,以便您成功继承了父原型。 唯一的问题是ChildConstructor.prototype.constructor现在指向TempConstructor

    继承父级原型尝试#4

    // Good
    var TempConstructor = function(){};
    TempConstructor.prototype = ParentConstructor.prototype;
    ChildConstructor.prototype = new TempConstructor();
    ChildConstructor.prototype.constructor = ChildConstructor;
    

    全部一起

    var ParentConstructor = function(){
    };
    
    
    var ChildConstructor = function(){
        ParentConstructor.call(this)
    };
    
    var TempConstructor = function(){};
    TempConstructor.prototype = ParentConstructor.prototype;
    ChildConstructor.prototype = new TempConstructor();
    ChildConstructor.prototype.constructor = ChildConstructor;
    

    您已成功从父类继承! 让我们看看我们能否做得更好。

    继承函数

    function inherits(childConstructor, parentConstructor){
        var TempConstructor = function(){};
        TempConstructor.prototype = parentConstructor.prototype; // Inherit parent prototype chain
    
        childConstructor.prototype = new TempConstructor(); // Create buffer object to prevent assignments directly to parent prototype reference.
        childConstructor.prototype.constructor = childConstructor; // Reset the constructor property back the the child constructor (currently set to TempConstructor )
    };
    
    
    var ParentConstructor = function(){
    };
    
    
    var ChildConstructor = function(){
        ParentConstructor.call(this)
    };
    inherits(ChildConstructor, ParentConstructor);
    
    链接地址: http://www.djcxy.com/p/5095.html

    上一篇: descendants override each other

    下一篇: Call a parent class's method from child class in Python?