为什么可以像数组一样查询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
。 这意味着,它确实是一个“真正的”对象(事实上,所有“数组”都是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]
看到这一点
但我们仍然可以在该对象上调用我们的方法.aNiceFunction()
。 通过使用Array.prototype.push()
方法将新元素推送到我们的对象上,ECMAscript将自动为我们索引这些元素。 这是简短描述jQuery引擎盖下发生的事情。
关于ECMAscript中“arrays”的另一个词。 这种语言中没有真正的数组(如果我们忘记了一秒钟的类型化数组 )。 只有Object
。 如果我们有一个inheritance自Array.prototype
的对象,我们几乎将它称为数组。 我们剩下要做的就是将.length
属性设置为0
。
jQuery对象是类似于数组的对象。
类数组对象是一个普通对象,它具有与数组相同的属性。
像object这样的数组的length
属性设置为正整数,属性名为0
,… length − 1
包含数组对象。
像数组一样处理jQuery对象是duck typing的应用程序。 来自维基百科 :
在使用面向对象编程语言的计算机编程中,duck typing是一种动态类型,其中对象的当前方法和属性集确定有效语义,而不是从特定类或特定接口的实现inheritance。
换句话说, 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"; } };
我不确定这种“arrays式”的疯狂是什么来自其他答案。 “arrays式”没有标准术语。
这里的实际差异是实际数组与链接列表之间的差异,实际数组是元素的集合,而链接列表是引用的集合。 在参考DOM时,链表被正确地称为节点列表。 这些文章有更多信息:
http://www.sitepoint.com/a-collection-is-not-an-array/
http://blog.duruk.net/2011/06/19/nodelists-and-arrays-in-javascript/