2012-01-29 6 views
7

リファレンス「厳格な使用」:http://ejohn.org/blog/simple-class-instantiation/ジョンResig氏の単純なクラスのインスタンス化と

// 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); 
    }; 
} 

を同じ機能を実装するための任意のECMAScriptの5準拠した方法がある場合、私は、思っていました。問題は、strictモードではarguments.calleeへのアクセスが推奨されなくなりました。

答えて

4

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

回避策は、匿名性を許すならば、名前付きの匿名関数を使用することです。本当に私は"named function expressions"と言うべきです。例は:

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

あなたが提供する名前、私の例ではfuncExpressionNameはどこでも、それが適用される関数の内部を除いてからアクセスできるように想定されていないが、残念ながらIEは他のアイデアを持っている(あなたが見ることができるようであれば、あなたGoogle it) 。例えば

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

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); 

しかし、それは NNNNNN によって与えられた上記のアイデアはかなり良いです

this.init.apply(this, args && args.callee ? args : arguments); 
2

次の行を使用して修復することができます。 IEの問題を回避するために、私は以下の解決策を提案します。我々は内部フラグを使用して// do something部分でargs.calleeへの参照を避ける方法

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; 
} 

注意。

関連する問題