【问题标题】:What is the actual type of the object jQuery is returning [duplicate]jQuery返回的对象的实际类型是什么[重复]
【发布时间】:2013-09-09 23:45:20
【问题描述】:

就像$ 本身不仅仅是一个用户定义的对象(它在其基础上是一个函数,这就是为什么您可以在其上使用() 运算符,它继承了Function.prototype 的所有函数) 所谓jQuery 对象的实际Javascript type 是什么?

它必须是标准的类数组对象之一,因为您可以在其上使用 [] 运算符,这在 IE8 中甚至不能对字符串执行(不,您不能,不是对象String。您可以在装箱之前对字符串文字进行处理)。
再说一遍,它不是用户定义的对象(注意没有jQuery 对象之类的东西,它是用原始javascript 编写的)。我感觉它是 NodeList(或在没有 NodeList 的浏览器中的等价物)。

您可能已经注意到这一点的一个原因是您向Array 原型添加了方法,但您发现该函数在 jQuery 找到的一组节点上不存在!

那么,有足够了解 jQuery 的人与我分享这些较低级别的信息吗?或者是否有一个简短的、详尽的 Javascript 中类似数组的对象列表,我可以测试 jQuery 对象,直到我发现它是我自己?


我之所以问这个问题,而不是假设 jQuery 只是向对象添加元素,而是使用索引作为属性名称(即obj[0] = x;),是因为 Chrome 开发工具和 Firebug 显示它们的方式。
@ 987654324@
这显示了显示数组、jQuery 和类数组对象的开发工具,并且 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

【问题讨论】:

  • 类似于this,但低于this。我对抽象不感兴趣
  • 这是一个函数。一旦你用它选择元素,返回的是一个类似数组的对象,因为它实际上只是一个对象,但它看起来很臭,感觉就像一个数组。这就是为什么它有一些数组方法,但不是全部。
  • [] 运算符不是“方法”。你不能把它给任何你想要的东西;它不是具有一些数组方法的用户定义对象。
  • 调用 jQuery 函数返回的对象只是普通对象。与任何对象一样,您可以使用括号表示法(即obj[prop])访问它的属性。 jQuery 使用数字属性名称(实际上是字符串),添加了一个长度属性,如果我没记错的话,还添加了 splice。这足以创建一个类似数组的对象。
  • 只是为了改善 SO 社区:是你写问题的方式。

标签: javascript jquery object


【解决方案1】:

我的理解是Array的一个子类,继承自Array Class,有自己的方法

以上改动:

它不是 Array 的子类。但它是由Array构成的,但是在Array对象创建之后,jQuery用jQuery自己的原型改变了对象原型,最终变成了jQuery对象,也就是类Array对象。

【讨论】:

  • 那么它应该从Array.prototype获取所有功能。 Javascript 中没有类,也没有子类(如果您以一种您会谈论 Java 的方式引用它)
  • 谢谢你的回答,我看到你没有问任何问题,但还是花时间回答别人的问题,你很好竖起大拇指 :)
  • javascript 没有类似 java 的类,但有它自己的原型类,你可以像 class 那样做。从 jQuery 创建者查看这篇文章:link
  • 这是一个扩展一个特定数组的方法的例子,但不影响另一个数组对象。jsfiddle
  • -1,它根本不是数组的子类。
【解决方案2】:

什么是 jQuery 对象?

$()jQuery() 函数返回一个 jQuery 对象。它不是Array 也不是NodeList,也不是从其中任何一个派生而来的。它是使用jQuery 构造函数(实际上是jQuery.fn.init() 函数)创建的Object。这个对象与使用new SomeConstructor() 创建的任何其他Object 非常相似,甚至是一个普通的对象字面量。

当您在没有new 运算符的情况下调用$()jQuery() 时,它是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 代码中直接在对象中设置的属性。它还有许多来自其原型的属性和方法,即jQuery.fnjQuery.prototypejQuery.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 开发者工具。他们都寻找两个特定的属性来决定将一个对象显示为一个数组:

  1. length 属性,可以是数字或包含数字的字符串。
  2. splice 属性是一个函数。

如果对象同时具有这两个属性,则显示为数组。

您可以通过将以下行粘贴到 Chrome DevTools 或 Firebug 中来测试:

({ splice:function(){}, length:0 })

Chrome 显示器:

[]

萤火虫显示:

Object[ ]

删除任一属性,它将显示为一个对象。

这些属性是在对象本身还是在它的原型中并不重要。您可以将此代码粘贴到任一控制台中,它将显示与上述代码相同的类似数组的符号:

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)

萤火虫显示:

Object[ body ]

您可以单击单词Object 以获得jQuery 对象的完整对象样式显示,而不是类似数组的显示。

Chrome 没有这种区别;它以相同的方式显示Array 或类似数组的Object

所以这就是魔法。它在 jQuery 中确实没有什么特别之处,只是它返回的对象确实具有 lengthsplice 属性。 splice() 方法在原型上,length 属性可能来自原型(对于空“数组”)或更常见的是来自 jQuery 对象本身。

这两个属性触发了真正的魔力:在 DevTools 和 Firebug 中尝试为此类对象提供更有用的显示。

吹牛的权利:-)

一些历史琐事:我实际上负责 jQuery 架构的这一部分。 2006 年初 jQuery 的第一个版本并不是这样工作的。 jQuery 对象没有.length[0][1] 等属性。相反,它有一个自己的“私有”数组,您必须使用 .get(n) 从该数组中获取值。

我认为直接以​​类似数组的方式访问元素会更方便,并提出设置.length[0][1] 等属性的想法,这样它就可以像只读数组。

【讨论】:

  • 我从未说过它源自Array。事实上,我说的恰恰相反。但是,我假设它派生自 其中一个 类数组对象类型并没有错,因为它具有指示这些类型的 operators (可以分配属性,是的。操作符(即[]);不是那么多)。 jQuery 可以解决这个问题的唯一方法是为每个找到的元素分配 index 属性。例如jQueryObj = new Object(); jQueryObj[0] = foundEl1; jQueryObj[1] = foundEl2;
  • 我无意冒犯,抱歉。我在答案中添加了更多信息,这应该有助于澄清。 jQuery 返回对象实际上只不过是使用 new 运算符创建的标准 JavaScript Object
  • 老实说,我跳过了 jQuery 会迭代每个索引,将它们作为属性添加到自身的概念,因为我认为这很浪费。我假设它正在使用 sizzle 或其他东西获取一个数组,然后使其成为自己的(通过覆盖原型或其他花哨的东西)。我想这很简单,我希望我保持足够的开放心态,看到 jQuery 从一开始就使用了最简单的方法
  • @Hashbrown:在 javascript 中,[] 运算符适用于 Objects,而不是 Arrays。数组可以使用[] 运算符的唯一原因是数组本身就是对象。 [] 运算符与 . 运算符一样可以访问对象中的属性和方法,但 [] 运算符需要一个字符串或数字,而 . 使用裸字。
  • @MattGreer 在对该问题的评论中指出了这一点,我知道这一点,这是我在您上面的评论中的假设,这是我的错误,而不是这个。我认为 jQuery 对象本质上是一个集合,而不是一个具有枚举属性的简单对象(如['0'], ['1'], ['2'] 等)。实际上,如果您阅读此答案的第一条评论的最后一句话,您会发现我理解了这一点。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-02-03
  • 1970-01-01
  • 2015-05-20
  • 2014-07-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多