为什么可以像数组一样查询jQuery('div')?



我得到了另一个关于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是如何做到这一点的,以了解它是否比我的解决方案更好。

jQuery对象就是我们所说的Array-like object。这意味着,它确实是一个"true"对象(事实上,所有"数组"都是ECMAscript中的对象),但它拥有某些属性,这些属性使它看起来像一个"true"数组。这些属性是
  • 作为.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]

看看的作用

但是我们仍然能够在该对象上调用我们的方法CCD_ 6。通过使用Array.prototype.push()方法将新元素推送到我们的对象上,ECMAscript将自动为这些元素建立索引。

ECMAscript中还有一个关于"数组"的词。这种语言中没有真正的数组(如果我们暂时忘记了类型化数组的话)。只有Object。如果我们有一个从Array.prototype继承的对象,我们几乎会把它称为数组。我们要做的就是将.length属性设置为0

jQuery对象是类似数组的对象。

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

像数组一样处理jQuery对象是鸭子类型的应用程序。来自维基百科:

在使用面向对象编程语言的计算机编程中,duck类型是一种动态类型,其中对象的当前一组方法和属性决定了有效的语义而不是从特定类或特定接口。

换句话说,jQuery函数实际返回数组实例并不重要,只要它提供了必要的属性(,例如length,数字索引)和方法,使数组一样工作。

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

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

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

这里的实际区别是实际数组(元素的集合)与链表(引用的集合)之间的区别。在引用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/

最新更新