【问题标题】:John Resig's simple class instantiation and "use strict"John Resig 的简单类实例化和“使用严格”
【发布时间】:2012-02-21 21:21:09
【问题描述】:

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

我想知道,是否有任何符合 ECMAScript 5 的方法来实现相同的功能。问题是,在严格模式下不推荐访问arguments.callee

【问题讨论】:

    标签: javascript ecmascript-5 use-strict


    【解决方案1】:

    据我了解,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 的使用将被替换.

    【讨论】:

      【解决方案2】:

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

      【讨论】:

        【解决方案3】:

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

        请注意我们如何通过使用内部标志来避免在 // do something 部分中引用 args.callee

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2012-06-19
          • 1970-01-01
          • 1970-01-01
          • 2011-09-19
          • 2011-12-15
          • 2011-04-18
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多