javascript继承模式混乱

时间:2012-10-18 08:40:09

标签: javascript jquery

我发现这是最常用的在javascript中进行继承的方法。

function extend(Child, Parent) {
 var F = function(){};
 F.prototype = Parent.prototype;
 Child.prototype = new F();
}

如果我已经有了孩子原型中的方法,那么它们是否会覆盖,我们不应该保留它们。

function extend(Child, Parent) {
 var c = child.prototype;
 var oldProto = new C();  
 var F = function(){};
 F.prototype = Parent.prototype;
 Child.prototype = new F();
 for(var i in oldProto ){
   Child.prototype[i] = oldProto[i]  
 }  
}

3 个答案:

答案 0 :(得分:2)

我不确定这对你有什么好处,但要记住这一点非常重要:原型与类不同。你正在做的是试图让JS表现得像传统的OO语言,它试图教海豚跳芭蕾舞,或者迫使老虎变成素食主义者:令人钦佩,但注定会以泪水结束。

我真的不明白你为什么要使用extend函数去做你想做的事情。为什么不简单地使用它:

function Parent()
{};
function Child()
{};
//augment parent proto
Parent.prototype.parentMethod1 = function()
{};
//set Child's proto to Parent
Child.prototype = new Parent();
Child.prototype.constructor = Child;
//Then augment the Child's prototype
Child.prototype.childMethod1 = function()
{};
var foo = new Child();
foo.parentMethod1();//works
foo.childMethod1();//works, too

IMO,这完全解决了这个问题。当然,它有点冗长,但OOP总是如此。

答案 1 :(得分:0)

您尝试实现的模式称为multiple inheritance。由于您遇到的问题(称为钻石问题),因此不建议使用它。只需使用mixin pattern代替。

答案 2 :(得分:0)

下面的代码是我在JavaScript中进行继承的最佳代码之一。

在MDN here上讨论了Object.create(proto [,propertiesObject])。

下面,Jon定义了一个名为ExtendBase的基本空对象,然后添加了一个名为extend的函数属性,该属性不是可枚举的,它将一个新对象作为其参数。

该对象应包含可枚举的属性,例如将添加到基础对象的方法和数据。

他从传递的对象中获取所有可枚举属性,然后创建一个必要描述符数组,以使用这些属性的名称传递给Object.create。然后,他使用父对象作为原型,并将结果描述符作为新属性直接添加到Object.create()调用中的子对象。

正如您所看到的,您可以使用带有属性的对象参数(包括方法)来扩展父对象,而不会丢失传递的对象的属性,结果是父对象作为原型的子对象以及传递的可枚举对象对象直接添加到孩子身上。

然而,这维护了一个干净的原型链,同时打算使用其他对象来扩展父对象,这些对象是以一种有意义的方式将父级扩展为新的子级:

实时样本here(在Chrome中输入F12作为控制台输出,或在FireFox中使用FireBug等)

JavaScript的:

// Original Author:  FireFly - Jonas Höglund - ##javascript channel
// on irc.freenode.net - see THANKS File.  Updated to private data
// members and passable initial parameters by Scott Sanbar

///////////////
// Library code
///////////////

var ExtendBase = {};

Object.defineProperty(ExtendBase, 'extend', {
    enumerable:false, value:function (obj) {
        'use strict';

        var descs = {};

        Object.getOwnPropertyNames(obj).forEach(function (key) {
            descs[key] = Object.getOwnPropertyDescriptor(obj, key)
        });

        return Object.create(this, descs);
    }
});

///////////////
// Sample Usage
///////////////

function PersonObj(nam) {

    return {
        name:new function () {

            var name = nam;

            this.set = function (value) {
                name = value;
            };

            this.get = function () {
                return name;
            }
        },

        // A person can tell you its name.
        talk:function () {
            return "Hello, I'm " + this.name.get();
        }
    }
}
;

function WorkingPersonObj(occ) {

    return {

        occupation:new function () {

            var occupation = occ;

            this.set = function (value) {
                occupation = value;
            };

            this.get = function () {
                return occupation;
            }
        },

        // A working person also tells you their occupation when they talk.
        talk:function () {
            return Person.talk.call(this) + " and I am a " + this.occupation.get();
        }
    }
}
;

var hush = {

    hush:function () {
        return "I am supposed to be quiet";
    }
};

var Person = ExtendBase.extend(new PersonObj('Harry'));
var WorkingPerson = Person.extend(new WorkingPersonObj('wizard'));

var wp1 = WorkingPerson.extend(hush);

console.log(wp1.talk()); // "Hello, I'm Harry and I am a wizard"
console.log(wp1.hush()); // "I am supposed to be quiet"
wp1.name.set("Elijah");
wp1.occupation.set("prophet");
console.log(wp1.talk()); // "Hello, I'm Elijah and I am a prophet"
console.log(wp1.name.get());
console.log(wp1.occupation.get());