【问题标题】:Why does jQuery use "new jQuery.fn.init()" for creating jQuery object but I can't?为什么 jQuery 使用“new jQuery.fn.init()”来创建 jQuery 对象但我不能?
【发布时间】:2009-12-06 22:40:11
【问题描述】:

我尝试创建一些基于 jQuery 样式的类,如以下代码。

myClass = window.myClass = function(x, y)
{
    return new myClass.fn.init(x, y);
};

myClass.fn = myClass.prototype = 
{
    init: function(x, y)
    {
        // logic for creating new myClass object.
    }
};

我不明白为什么 jQuery 使用 new 关键字来创建它的类,因为根据我的实验,JavaScript 总是创建 myClass.init 对象而不是 myClass 对象。但是,我尝试在 myClass 构造函数中删除 new 关键字。但它仍然没有改变。你能解释一下为什么 jQuery 可以做到这一点,但我不能,或者给我一些在 init 函数中使用的代码吗?

顺便说一句,我可以使用以下代码而不是 jQuery 样式代码来创建相同的对象。我的代码和 jQuery 代码有什么不同?使用 jQuery 样式有什么好处吗?

myClass = window.myClass = function(x, y)
{
    this.init(x, y);
};

myClass.fn = myClass.prototype = 
{
    init: function(x, y)
    {
        this.x = x;
        this.y = y;
    }
};

PS。我喜欢编写将初始逻辑分离为函数的代码,因为使用我的代码的其他人很容易覆盖这个函数,就像我下面的代码一样。

// override init function of myClass
myClass.fn._old_init = myClass.fn.init;
myClass.fn.init = function()
{
    // logic for doing something before init

    this._old_init();

    // logic for doing something after init
};

谢谢,

【问题讨论】:

    标签: javascript jquery oop


    【解决方案1】:

    这种方法应该可以完美运行。您可能缺少的一件事是,使用这种技术,您将不会创建myClass 的实例;您将创建一个myClass.prototype.init 的实例。

    因此,myClass.prototype 中定义的任何方法都不可用于实例。您需要确保init 的原型指向myClass 的原型:

    myClass.fn.init.prototype = myClass.fn;
    

    FWIW,我认为这种方法没有任何真正的好处。这有什么问题? -

    function myClass(x,y) {
    
        if ( !(this instanceof myClass) ) {
            return new myClass(x,y);
        }
    
        // Prepare instance
    
    }
    
    myClass.prototype = { /* Methods */ };
    
    // It can still be overwritten:
    
    var oldMyClass = myClass;
    
    function myClass(x,y) {
    
        // Hack some stuff here...
    
        return new oldMyClass(x,y);
    }
    

    【讨论】:

    • 您的回答是正确的,因为我刚刚发现 jQuery 使用此语句 (jQuery.fn.init.prototype = jQuery.fn) 为 init 函数提供 jQuery 原型以供以后实例化。但是,您的回答和您的示例并没有解决我的问题,为什么 jQuery 使用这种样式来创建 jQuery 对象。
    • jQuery 可能使用这种技术将构造函数功能与通用包装函数 (jQuery()) 分开。他们可以做任何一种方式,这可能是 jQuery 开发早期做出的决定,并且没有改变,因为它似乎有效地工作......
    • @J-P - 同意这可能让人想起早期的决定
    • 也许这可以说明一些问题:mail-archive.com/jquery-en@googlegroups.com/msg45575.html 有趣的是jQuery.fn.init.prototype = jQuery.fn 的作者并没有看到它在 jQuery 之外的适用性。
    【解决方案2】:

    jQuery 对象初始化应该像下面的代码。

    jQuery = window.jQuery = window.$ = function (x, y)
    {
        return new jQuery.fn.init(x, y);
    };
    
    jQuery.fn = jQuery.prototype = 
    {
        init: function()
        {
            // some logic for object initialization
            return this;
        }
    };
    
    jQuery.fn.init.prototype = jQuery.fn;
    

    这段代码的唯一好处是它总是创建 jQuery 对象的实例,尽管你不使用 new 关键字来创建对象。

    另一方面,如果您在调用时不使用 new 关键字,我使用 init 函数初始化对象的代码将不起作用。为了修复它,您必须添加一些代码,例如“J-P”示例来检查此对象。如果它的类型不是当前类,它会自动为其创建实例。

    这两个代码都应该可以正常工作。但我更喜欢 jQuery 风格而不是“J-P”风格,因为它很容易阅读和修改。

    谢谢,

    【讨论】:

      【解决方案3】:

      我不完全确定问题是什么,但我会尽力回答我认为您要问的问题。

      new 关键字用于实例化由函数原型上的init 属性定义的函数返回的对象的新实例。

      我相信代码是以这种方式编写的,因此每次实例化一个新的 jQuery 对象时都不需要 new 关键字,并将对象构造背后的逻辑委托给原型.我相信前者是为了使库 cleaner 可以使用,而后者是为了将初始化逻辑干净地保存在一个地方,并允许递归调用 init 以构造并返回一个正确匹配的对象传递参数。

      您的第二个代码块没有返回对象。在 Firebug 中试用

      var myClass1 = myClass(1,2);
      console.log(myClass1);
      

      你得到this.init is not a function 错误。唯一可行的方法是使用new 关键字,如

      var myClass1 = new myClass(1,2);
      console.log(myClass1);
      

      与jQuery中类似的代码对比

      myClass = window.myClass = function(x, y)
      {
          return new myClass.fn.init(x, y);
      };
      
      myClass.fn = myClass.prototype = 
      {
          init: function(x, y)
          {
              this.x = x;
              this.y = y;
          }
      };
      
      var myClass1 = myClass(1,2);
      console.log(myClass1);
      
      var myClass2 = new myClass(1,2);
      console.log(myClass2);
      

      在每种情况下,无论是否使用 new 关键字,您都正确地返回了一个带有值为 1 的 x 属性和值为 2 的 y 属性的对象。

      【讨论】:

      • 我只是在我的回答中告诉你。当您不使用 new 关键字时,我的问题中的代码不起作用。
      • 从你的问题中的措辞不清楚这就是你所说的
      猜你喜欢
      • 2014-09-01
      • 2011-02-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-04-10
      • 1970-01-01
      • 2019-04-07
      相关资源
      最近更新 更多