7

Reference : 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 );
  };
}

I was wondering, if there are any ECMAScript 5 compliant way to implement the same functionality. The problem is, accessing arguments.callee is deprecated in strict mode.

4

3 回答 3

4

据我了解,在严格模式下arguments.callee推荐使用它,在这种情况下您可以继续使用它;相反,它已被删除并且尝试使用将(或应该)抛出异常。

解决方法是使用命名的匿名函数,如果你会原谅矛盾的话。真的我应该说“命名函数表达式”。一个例子:

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

在我的示例funcExpressionName中,您提供的名称不应该从任何地方访问,除了它适用的函数内部,但不幸的是 IE 有其他想法(如果您谷歌它,您可以看到)。

对于您问题中的示例,我不确定如何处理,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 回答