7

参照:http ://ejohn.org/blog/simple-class-instantiation/

// makeClass - By John Resig (MIT Licensed)
function makeClass(){
  return function(args){
    if ( this instanceof arguments.callee ) {
      if ( typeof this.init == "function" )
        this.init.apply( this, args.callee ? args : arguments );
    } else
      return new arguments.callee( arguments );
  };
}

同じ機能を実装するためのECMAScript5準拠の方法があるかどうか疑問に思いました。問題は、厳密モードではアクセスarguments.calleeが非推奨になることです。

4

3 に答える 3

4

私が理解しているように、厳密モードでarguments.callee非推奨ではありません。その場合、引き続き使用できます。むしろ、それは削除されており、使用を試みると例外がスローされる (またはスローされるはずです)。

回避策は、矛盾した表現を許すなら、名前付きの無名関数を使用することです。本当は「名前付き関数式」と言うべきです。例:

function someFunc(){
  return function funcExpressionName(args){
    if (this instanceof funcExpressionName) {
      // do something
    } else
      return new funcExpressionName( arguments );
  };
}

あなたが提供した名前は、私の例では、それが適用される関数内以外のどこからでもアクセスできるとは想定されていませんが、残念ながらIEには他のアイデアがあります( Googleで検索するとfuncExpressionNameわかるように)。

あなたの質問の例ではargs.callee、呼び出し元の関数によってどのように設定されているのかわからないため、の処理方法がわかりませんが、の使用はarguments.callee私の例に従って置き換えられます。

于 2012-01-30T01:26:24.090 に答える
2

nnnnnnによって与えられた上記のアイデアは非常に優れています。IE の問題を回避するために、次の解決策をお勧めします。

function makeClassStrict() {
    var isInternal, instance;

    var constructor = function(args) {
        // Find out whether constructor was called with 'new' operator.
        if (this instanceof constructor) {
            // When an 'init' method exists, apply it to the context object.
            if (typeof this.init == "function") {
                // Ask private flag whether we did the calling ourselves.
                this.init.apply( this, isInternal ? args : arguments ); 
            }
        } else {
            // We have an ordinary function call.

            // Set private flag to signal internal instance creation.
            isInternal = true;                                           
            instance = new constructor(arguments);
            isInternal = false;                                         
            return instance;
        }
    };

    return constructor;
}

内部フラグを使用してargs.callee、パーツ内での参照を回避する方法に注意してください。// do something

于 2013-07-11T08:01:46.890 に答える
1

John Resig の元のコードは、パラメーターなしのコンストラクターで失敗します。

var Timestamp = makeClass();
Timestamp.prototype.init = function() {
    this.value = new Date();
};

// ok
var timestamp = Timestamp();
alert( timestamp.value );  

// TypeError: args is undefined
var timestamp = new Timestamp();
alert( timestamp.value );   

ただし、次の行を使用して修復できます

this.init.apply( this, args && args.callee ? args : arguments );
于 2013-07-10T12:50:21.547 に答える