【问题标题】:Why is it possible to query jQuery('div') like an array?为什么可以像数组一样查询 jQuery('div')?
【发布时间】:2012-01-09 18:05:12
【问题描述】:

我有另一个关于 jQuery 架构的问题。 $('div') 构造一个新的jQuery 对象:

$('div') instanceof jQuery; // true

我想知道为什么可以像数组一样查询它,尽管它不是数组?

$('div')[0]; // returns the first div in the document as a DOM node.
$.isArray($('div')); // false

我就是喜欢这种语法,它看起来很干净!我还注意到这会将 DOM 节点作为数组返回:

console.log($('div'));

谁能解释我如何对我自己的对象实现这种行为?


我自己的方法是用这样的一些方法制作一个数组:

var a = ['a', 'b', 'c'];
a.method = function(){ return 'test'; };
a; // ['a', 'b', 'c']
a[0]; // 'a'
a.method(); // 'test'

然而这似乎不是 jQuery 的做法,因为这实际上是一个数组:

$.isArray(a); // true

我想知道 jQuery 是如何学习的,看看它是否比我的更好。

【问题讨论】:

  • 您可以使用 [ ] 表示法访问 any 属性。不仅仅是指数。所以就像$('div')[0],你可以做$('div')['jquery'],它会给你jQuery的版本号。
  • @amnotiam 我知道。但是当我在控制台中打印普通对象时,它们不会输出数组。
  • 啊,如果您专门询问控制台输出,那么实际上只是控制台对您给出的内容做出了最佳猜测。 jAndy's answer 展示了控制台通常会做什么。
  • 示例:console.log({"2":"foo",splice:function(){},length:2}); 显然不是正在记录的数组,而是显示为 [undefined, undefined, "foo"]

标签: javascript jquery


【解决方案1】:

jQuery 对象就是我们所说的Array-like object。这意味着,它确实是一个“真实”对象(事实上,所有“数组”都是 ECMAscript 中的对象),但它拥有某些属性,使其看起来像一个“真实”数组。这些属性是

  • 它是.length 属性
  • 它拥有.splice() 方法

这两个事实足以让大多数 js 引擎 控制台将该对象解释为数组。

示例

var myObject = { },
    push = Array.prototype.push;

myObject.aNiceFunction = function() {
    console.log(this);
};

push.call( myObject, document.getElementById('foo') );
push.call( myObject, document.getElementById('bar') );

myObject.splice = Array.prototype.splice;

如果我们现在记录我们的对象

console.log( myObject );

我们得到了典型的 jQuery'ish 结果

[div#foo, div#bar]

See that in action

但我们仍然可以在该对象上调用我们的方法.aNiceFunction()。通过使用Array.prototype.push() 方法将新元素推送到我们的对象上,ECMAscript 会自动为我们索引这些元素。这是 jQuery 引擎盖下发生的事情的简短描述。

关于 ECMAscript 中“数组”的更多信息。这种语言中没有真正的数组(如果我们暂时忘记typed arrays)。只有Object。如果我们有一个继承自Array.prototype 的对象,我们几乎可以称它为数组。我们剩下要做的就是将.length 属性设置为0

【讨论】:

  • JS 引擎不会将任何内容解释为数组。 JS users 将事物解释为数组。 :)
  • @SLaks:触摸。我的意思是,例如它是如何被控制台对象“注销”的。
  • 这是 Firebug 的 / Chrome 的漂亮打印机(是 JS 用户)的功能,而不是 JS 引擎。
【解决方案2】:

jQuery 对象是 类数组 对象。

类数组对象是具有与数组相同的属性的普通对象。
类似数组的对象有一个设置为正整数的length 属性,以及名为01、... length − 1 的属性,其中包含数组对象。

【讨论】:

    【解决方案3】:

    像处理数组一样处理 jQuery 对象是 duck typing 的应用。 From Wikipedia:

    在使用面向对象编程语言的计算机编程中, 鸭子类型是一种动态类型,其中对象的当前 一组方法和属性决定了有效的语义,而不是 而不是它从特定类或实现的继承 具体界面。

    换句话说,jQuery 函数实际上返回一个数组实例并不重要,只要它提供必要的属性(例如 length,数字索引)和方法表现得像一个数组。

    JavaScript 还有其他类数组 对象。例如,arguments 对象也不是数组,但它具有允许您假装它是的属性(如 length)。

    【讨论】:

      【解决方案4】:

      jQuery 对象是“类数组”对象。考虑下面的代码:

      document.forms.length; // returns 1;
      document.forms[0]; // returns a form element.
      document.forms.join(", "); // throws a type error. this is not an array.
      typeof document.forms; // returns "object"
      

      修改你的代码,你可以达到同样的效果:

      var a = 
      {
          0: 'a',
          1: 'b',
          2: 'c',
          length: 3,
          method: function() {
              return "test";
          }
      };
      

      【讨论】:

      • console.log(a) 打印对象而不是数组。所以这似乎不是 jQuery 的方式。顺便说一下,我不是 JavaScript 初学者,我知道 JavaScript 对象是如何工作的。
      【解决方案5】:

      我不确定其他答案中的这种“类似数组”的疯狂是什么。 “类数组”没有标准术语。

      这里的实际区别是实际数组(元素集合)与链表(引用集合)之间的区别。在参考 DOM 时,链表被恰当地称为节点列表。这些文章有更多信息:

      http://www.mindcracker.com/Story/1016/interview-question-difference-between-linked-list-and-array.aspx

      http://www.sitepoint.com/a-collection-is-not-an-array/

      http://blog.duruk.net/2011/06/19/nodelists-and-arrays-in-javascript/

      【讨论】:

        猜你喜欢
        • 2014-08-10
        • 2010-11-21
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多