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を伝統的なオブジェクト指向言語のように振る舞わせることです。これは、イルカにバレエを踊らせることを教えようとしている、またはトラをビーガンにさせようとしていることです。

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 で継承を実行するために私が見た中で最高のものの 1 つです。

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 に答える