3

Javascriptでの単純な「クラス」インスタンス化に関するJohnResigの投稿で、彼は次のように述べています。

「...頻繁にアクセスする(オブジェクトを返す)関数を使用して、ユーザーが操作できるようにする場合は、オブジェクトのプロパティをプロトタイプチェーンに含めてインスタンス化することをお勧めします。これは、コード内にあります。 :"

// Very fast
function User(){}
User.prototype = { /* Lots of properties ... */ };
// Very slow
function User(){
    return { /* Lots of properties */ };
}

これを次のような関数に適用したいと思います(これはたまたま「クラス」宣言内にあります)

//...
this.get_subscription = function(args)
{
    return {
        property_one: "value",
        property_two: {
            sub_prop: args.something
        }
    }
}

しかし、引数をどこに置くべきかわかりません。私が行った場合

this.get_subscription = function(args) {}
this.get_subscription.prototype = {
    property_one: "value"
    //...
}

argsは未定義であると表示されます。私はいくつかのバリエーションを試しましたが、どれも機能しません。親クラスのスコープに引数を入れない方法で、これを適切に行うにはどうすればよいですか?

4

2 に答える 2

3

あなたはのポイントを誤解しているようですprototype。プロトタイプは、オブジェクトのすべてのインスタンスに共通である必要があるメソッドとフィールドを保持します。したがって、がコンストラクターに渡されたものにproperty_two基づいている場合、それはプロトタイプに属していません。args

結局のところ、このコードでは

this.get_subscription = function(args) {}
this.get_subscription.prototype = {
    property_one: "value"
    //...
}

最初に関数get_subscriptionが作成され、次にそのプロトタイプがオブジェクトリテラルに設定されます。コンストラクターを呼び出すまではないので、プロトタイプでargs何かを行うのは意味がありません。args

したがって、通常のjavascriptオブジェクトは次の例のようになります-2Dポイントクラス。

function Point(x, y) {
    /*  In constructor:
     *  initialize fields that are related to the constructor parameters
     *  and are different for different instances
     */
    this.x = x;
    this.y = y;
}

// in prototype, define fields that are  common to all instances
Point.prototype.RED = '#FF0000';

/*  in prototype, also define the methods; as they can use the "this" keyword,
 *  they can reference their own instance, so you don't have to include them
 *  in each instance manually
 */

Point.prototype.toString = function() { return '[' + this.x + ', ' + this.y + ']'; };
于 2012-05-02T23:32:48.937 に答える
1

はい、それが「プロトタイプへのすべて」の欠点です。アイデア:コンストラクター引数にアクセスできません。これらは関数本体でのみ使用できます(パブリックプロパティに配置する場合を除く)。それらを使用する必要があるものはすべてプロトタイプに属していません。プロトタイプ(通常はすべてのインスタンスに共通のメソッド)に「デフォルトのプロパティ」を入力するだけです。

とにかくここでは必要ないと思います。このパターンは、ここにはないように見える実際のコンストラクター関数にのみ役立ちます(私はそうなると思いますthis.Subscription)。また、約束された「パフォーマンスの向上」はごくわずかです。

本当にここで使用したい場合は、次のようになります。

function Class() {
   this.Subscription = function(args) {
       this.propertyTwo = {
           subprop: args.something
       };
   };
   this.Subscription.prototype = {
       property_one: "value",
       property_two: {}
   };
}
// a method callable without the "new" operator:
Class.prototype.get_subscription = function(args) {
     return new this.Subscription(args);
}

利用方法:

var object = new Class();
var sub = new object.Subscription();
var sub2 = new object.Subscription();
// the promised boost is less memory usage for:
sub.propertyOne === object.Subscription.prototype.propertyOne === sub2.propertyOne;

また、 Crockfordのプロトタイプの継承にも注意してください。オブジェクトのプロパティを設定/変更/削除しようとすると、ネストされたオブジェクトに関する問題が発生しますpropertyTwo

于 2012-05-02T23:34:31.417 に答える