1

我发现这是在 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]  
 }  
}
4

3 回答 3

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 总是如此。

于 2012-10-18T08:58:35.730 回答
0

下面的代码是我见过的最好的 JavaScript 继承代码之一。

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

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

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

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

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

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

现场示例(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());
于 2012-10-18T10:07:19.143 回答
0

您尝试实现的模式称为多重继承。由于您遇到的问题,称为钻石问题,因此强烈不建议使用它。只需使用mixin 模式

于 2012-10-18T08:57:24.947 回答