Why is it possible to query jQuery('div') like an array? (5 个回答)
7年前关闭。
就像
$
本身不仅仅是一个用户定义的对象(它在其基础上是一个函数,这就是为什么你可以在它上面使用
()
运算符并且它继承了
Function.prototype
的所有函数)什么是实际的 Javascript
type
所谓的
jQuery 对象?
它必须是标准的类数组对象之一,因为您可以在其上使用
[]
运算符,您甚至无法在 IE8 中对字符串执行此操作(不,您不能,不能在 Object
String
上执行。您可以在字符串文字被装箱之前)。
再说一次,它不是用户定义的对象(注意,没有
jQuery
对象这样的东西,它是用原始 javascript 编写的)。我有一种感觉,它是
NodeList
(或在没有
NodeList
的浏览器中等效)。
您可能已经注意到这一点的一个原因是您已经向
Array
原型(prototype)添加了方法,并且您发现该函数在 jQuery 找到的一组节点上不存在!
那么是否有人对 jQuery 足够了解可以与我分享这些较低级别的信息?或者是否有一个简短的、详尽的 Javascript 类数组对象列表,我可以测试 jQuery 对象,直到我找出它是我自己的对象?
我问这个的原因,而不是假设 jQuery 只是向对象添加元素,而是使用索引作为属性名称(即
obj[0] = x;
)是因为 Chrome 开发工具和 Firebug 显示它们的方式。
这显示了显示 Array、jQuery 和 Array-like 对象的开发工具,并且 jQuery 所做的事情背后至少有一些魔法。
编辑
它不是
NodeList
。如果有帮助;在 Chrome 中检查它表明它是
jQuery.fn.jQuery.init[0]
类型,
__proto__
将自身描述为
Object[0]
(它具有所有 jquery 方法)。任何解释 jQuery 是什么以及如何做的人都会非常感谢。我现在要查看 jQuery 的源代码。
至于图像,它不仅仅是一个被覆盖的
.toString()
。
$('').toString == Object.prototype.toString //true
$('').toString == Array.prototype.toString //false
什么是 jQuery 对象?
$()
或 jQuery()
函数返回一个 jQuery
对象。它不是 Array
也不是 NodeList
,也不是从任何一个派生出来的。它是使用 Object
构造函数(实际上是 jQuery
函数)创建的 jQuery.fn.init()
。这个对象非常像任何其他用 Object
创建的 new SomeConstructor()
,甚至是一个普通的对象文字。
当您在没有 $()
运算符的情况下调用 jQuery()
或 new
时,它是 automatically does a new
for you :
jQuery = function( selector, context ) {
// The jQuery object is actually just the init
// constructor 'enhanced'
return new jQuery.fn.init( selector, context, rootjQuery );
},
jQuery
对象有点“类似数组”,因为它具有带数字索引的属性和
.length
属性,但这些只是在 jQuery 代码中直接在对象中设置的属性。它还有许多来自其原型(prototype)的属性和方法,即
jQuery.fn
或
jQuery.prototype
(
jQuery.fn
只是对
jQuery.prototype
的引用;它们是同一个对象。)
您可以在
jQuery code that wraps a DOM element when you use $(element)
中看到这样的示例:
// HANDLE: $(DOMElement)
} else if ( selector.nodeType ) {
this.context = this[0] = selector;
this.length = 1;
return this;
} ...
在这段代码中,
selector
实际上是一个 DOM 元素,代码将该元素存储在
this[0]
中,并将
this.length
设置为
1
。这就是您可以使用
[0]
和
.length
的原因,因为对象具有这些显式设置的属性。
为什么 jQuery 对象像数组一样显示?
这里有一些魔法,但魔法在于 Firebug 和 Chrome 开发者工具。他们都寻找两个特定的属性来决定将一个对象显示为一个数组:
length
属性,它是一个数字或一个包含数字的字符串。 splice
属性,它是一个函数。 如果对象同时具有这两个属性,则它会显示为一个数组。
您可以通过将以下行粘贴到 Chrome DevTools 或 Firebug 中来对此进行测试:
({ splice:function(){}, length:0 })
Chrome 显示:
[]
Firebug 显示:
Object[ ]
删除任一属性,它将显示为一个对象。
这些属性是否在对象本身或其原型(prototype)中并不重要。您可以将此代码粘贴到任一控制台中,它将显示与上述代码相同的类似数组的符号:
function A(){}; A.prototype = { splice:function(){}, length:0 }; new A;
您可以向“数组”中添加一个元素:
({ splice:function(){}, length:1, 0:'test' })
现在 Chrome 显示:
["test"]
和 Firebug 显示:
Object[ "test" ]
请注意,Firebug 显示与实际
Array
显示的内容并不完全相同。 Firebug 将
Object
前缀放在类似数组的显示前面,让您知道它不是实际的
Array
。
它也在 jQuery 对象上这样做。如果您输入:
$(document.body)
Firebug 显示:
Object[ body ]
您可以单击
Object
一词以获得 jQuery 对象的完整对象样式显示,而不是类似数组的显示。
Chrome 没有做出这种区分;它以相同的方式显示
Array
或类似数组的
Object
。
所以这就是魔法。它在 jQuery 中真的没有什么特别之处,只是它返回的对象确实具有
length
和
splice
属性。
splice()
方法在原型(prototype)上,
length
属性可能来自原型(prototype)(对于空的“数组”)或更常见的是来自 jQuery 对象本身。
这两个属性触发了真正的魔法:DevTools 和 Firebug 中的一个 hack 试图为这些对象提供更有用的显示。
吹牛的权利 :-)
一些历史琐事:我实际上负责 jQuery 架构的这一部分。 2006 年初的第一个 jQuery 版本并不是这样工作的。 jQuery 对象没有
.length
和
[0]
、
[1]
等属性。相反,它有一个自己的“私有(private)”数组,您必须使用
.get(n)
从该数组中获取值。
我认为对元素进行类似数组的直接访问会更方便,并想出了设置
.length
、
[0]
、
[1]
等属性的想法,这样它就可以像只读数组一样工作。