7

次の関数を使用して、引数の配列からJavaScriptで関数のインスタンスを作成します。

var instantiate = function (instantiate) {
    return function (constructor, args, prototype) {
        "use strict";

        if (prototype) {
            var proto = constructor.prototype;
            constructor.prototype = prototype;
        }

        var instance = instantiate(constructor, args);
        if (proto) constructor.prototype = proto;
        return instance;
    };
}(Function.prototype.apply.bind(function () {
    var args = Array.prototype.slice.call(arguments);
    var constructor = Function.prototype.bind.apply(this, [null].concat(args));
    return new constructor;
}));

上記の関数を使用すると、次のようにインスタンスを作成できます(フィドルを参照)。

var f = instantiate(F, [], G.prototype);

alert(f instanceof F); // false
alert(f instanceof G); // true

f.alert(); // F

function F() {
    this.alert = function () {
        alert("F");
    };
}

function G() {
    this.alert = function () {
        alert("G");
    };
}

上記のコードは、のようなユーザー作成のコンストラクターで機能しますFArrayただし、明らかなセキュリティ上の理由から、ネイティブコンストラクタでは機能しません。いつでも配列を作成してからその__proto__プロパティを変更できますが、私はRhinoでこのコードを使用しているため、そこでは機能しません。JavaScriptで同じ結果を達成する他の方法はありますか?

4

2 に答える 2

7

配列を完全にサブクラス化することはできません。

ただし、を使用Object.createして、現在のコードから多くの複雑さを取り除くことができます()。

于 2012-08-07T13:18:45.327 に答える
3

ここで意図していることを達成しているとは思いません。まず、F関数とG関数で、このオブジェクトにアラート関数を定義します。これは、オブジェクトをインスタンス化するたびに、新しい関数オブジェクトが作成され、アラートに割り当てられることを意味します。これはあなたが望むものではありません、あなたはFとGのプロトタイプでアラートを定義する必要があります。

function F() { }

F.prototype.alert = function() {
    alert("F");
};

function G() { }

G.prototype.alert = function() {
    alert("G");
};  

ただし、インスタンス化機能にはまだ問題があります。あなたがそれをあなたが持っているように呼ぶなら

var f = instantiate(F, [], G.prototype);

あなたがしているのは、fのプロトタイプをG.prototypeに設定することだけです。これは、私が望むものではありません。Fオブジェクトをインスタンス化する場合は、F.prototypeで定義されているすべての関数を呼び出せるようにする必要があると思いますが、現状ではそうではありません。

function F() { }

F.prototype.alert = function() {
    alert("F");
};

F.prototype.foo = function() {
    alert("F foo");
};

function G() { }

G.prototype.alert = function() {
    alert("G");
};  


var f = instantiate(F, [], G.prototype);
f.foo(); // error!

ここでのエラーの理由は、fのプロトタイプをG.prototypeに割り当てるだけで、G.prototypeにはfoo関数が定義されていないということです。

この方法で継承を行うことを検討している場合は、John Resigのブログをご覧ください。彼にはすばらしい実装があります:http://ejohn.org/blog/simple-javascript-inheritance/

また、ダグラス・クロックフォードはいくつかの良い例をまとめました:http ://www.crockford.com/javascript/inheritance.html

于 2012-08-08T21:38:01.863 に答える