检查对象是否是jQuery对象

655
有没有一种快速的方法来检查一个对象是 jQuery 对象还是原生 JavaScript 对象?
例子:
var o = {};
var e = $('#element');

function doStuff(o) {
    if (o.selector) {
        console.log('object is jQuery');
    }
}

doStuff(o);
doStuff(e);
显然,上面的代码可以工作,但不安全。你可以向o对象添加一个选择器键,并获得相同的结果。有没有更好的方法来确保对象实际上是jQuery对象?
类似于(typeof obj == 'jquery')

3
截至jQuery 3.0版本,这绝对不是检查对象是否为jQuery对象的正确方法,因为selector属性早已被弃用并在3.0中删除。即使在早期版本中,jQuery对象也可以具有空选择器字符串,例如$(window)没有选择器。应改用instanceof - Dave Methvin
9个回答

944

您可以使用instanceof运算符:

if (obj instanceof jQuery){
    console.log('object is jQuery');
}
解释jQuery 函数(也称为 $)被实现为 构造函数。构造函数需要在前面加上 new 前缀进行调用。
当你调用 $(foo) 时,jQuery 会将其内部转换为 new jQuery(foo)1。JavaScript 接着会在构造函数内部初始化 this,使其指向一个新的 jQuery 实例,并将其属性设置为 jQuery.prototype(也称为 jQuery.fn)中找到的属性。因此,你会得到一个 instanceof jQuerytrue 的新对象。

1实际上是new jQuery.prototype.init(foo):构造函数逻辑已经转移到另一个名为init的构造函数中,但概念是相同的。


9
你的意思是 if (obj instanceof jQuery){...} 吗? - user1850421
2
@NigelAngel:是的,这就是他的意思 :) - ChaseMoskal
12
在页面上存在多个jQuery实例的情况下,这种方法无法正常工作。 - Georgii Ivankin
5
如果我在当前命名空间中有一个指向jQuery2的$变量,同时我有一个来自外部命名空间的对象(其中$是jQuery1),那么我无法使用instanceof检查该对象是否为jQuery对象。 - Georgii Ivankin
8
如果您不确定在if语句执行时jQuery是否已加载,您可以扩展检查条件为typeof jQuery === 'function' && obj instanceof jQuery,因为jQuery不一定需要被声明才能使typeof运算符正常工作而不抛出错误。 - Patrick Roberts
显示剩余4条评论

116

您也可以使用在此处描述的 .jquery 属性:http://api.jquery.com/jquery-2/

var a = { what: "A regular JS object" },
b = $('body');

if ( a.jquery ) { // falsy, since it's undefined
    alert(' a is a jQuery object! ');    
}

if ( b.jquery ) { // truthy, since it's a string
    alert(' b is a jQuery object! ');
}

13
正如David在问题中指出的那样,检查一个变量的属性,其值可能为null(即如果"a"或"b"为null),是不安全的(它会抛出TypeError)。使用"b instanceof jQuery"更好。 - rstackhouse
27
如果没有加载jQuery,这种方式可以工作,而b instanceof jQuery会在页面上没有可用的jQuery时抛出ReferenceError。这两种方法在不同情况下都很有用。 - Nate
或许更高效,但仍不安全。可能需要使用 try ... catch,特别是在旧版IE中。 - ClarkeyBoy
在可能没有加载jQuery的情况下,您可以使用 if ((typeof jQuery !== 'undefined') && (obj instanceof jQuery)) {... - Harry Pehkonen
这不是一个很好的例子。更有可能的情况是,a 将是一个 DOM 节点,比如 document.body,然后理论上存在一种可能性,即 jquery 键以某种方式出现在该节点的链顶部。 - vsync
假设您想编写一个函数,该函数接受Element和jQuery对象作为参数。使用instanceof需要您的库依赖于jQuery,而检查jquery属性则不需要。如果存在jquery,我更喜欢检查它并像处理任何类似数组的类型一样处理对象。这样,您就不会强制要求您的库客户端依赖于jQuery,同时允许那些有jQuery依赖的客户端传递其jQuery对象并期望您的函数正常工作。 - Şafak Gür

32

看看 instanceof 运算符。

var isJqueryObject = obj instanceof jQuery

26
检查对象实例的最佳方式是使用instanceof运算符或使用方法isPrototypeOf(),后者检查一个对象的原型是否在另一个对象的原型链中。请保留HTML标记。
obj instanceof jQuery;
jQuery.prototype.isPrototypeOf(obj);

但在文档中存在多个jQuery实例的情况下,有时它可能会失败。正如@Georgiy Ivankin所提到的:

如果我的当前命名空间中有$指向jQuery2,并且我有一个来自外部命名空间(其中$jQuery1)的对象,那么我无法使用instanceof检查该对象是否是jQuery对象

克服这个问题的一种方法是通过在闭包IIFE中为jQuery对象取别名。

//aliases jQuery as $
(function($, undefined) {
    /*... your code */

    console.log(obj instanceof $);
    console.log($.prototype.isPrototypeOf(obj));

    /*... your code */
}(jQuery1));
//imports jQuery1

另一种克服这个问题的方法是通过查询obj中的jquery属性。

'jquery' in obj

然而,如果你尝试对原始值进行这种检查,它会抛出一个错误,因此你可以通过确保 obj 是一个 Object 来修改前面的检查。

'jquery' in Object(obj)

虽然以前的方法不是最安全的(您可以在对象中创建'jquery'属性),但我们可以通过同时使用这两种方法来改进验证:

if (obj instanceof jQuery || 'jquery' in Object(obj)) { }

问题在于任何对象都可以定义自己的属性jquery,因此更好的方法是询问原型,并确保对象不为nullundefined
if (obj && (obj instanceof jQuery || obj.constructor.prototype.jquery)) { }

由于强制类型转换,当obj为任何假值(如nullundefinedfalse0"")时,if语句将通过评估&&运算符来进行短路,并继续执行其他验证操作。
最后,我们可以编写一个实用函数:
function isjQuery(obj) {
  return (obj && (obj instanceof jQuery || obj.constructor.prototype.jquery));
}

让我们来看一下:逻辑运算符和真值 / 假值

然而,这如何提高安全性呢?带有jquery属性的非jQuery对象仍将被错误检测。我也看不出同时使用两种方法还可能会“改进”些什么。 - Gui Prá
这是一种简单的方法来检查一个对象是否是jQuery对象,如果你怀疑有人正在创建带有_jquery_属性的对象,那么你可以创建一个更强大的验证器,即检查_prototype:_中的属性 myObj.constructor.prototype.jquery 或者更好的方法是使用函数 ***Object.prototype.isPrototypeOf()***。 - jherax
1
如果你将任何一个值 ||'jquery' in Object(obj) 结合使用,那么它就会失效,因为它不能防止具有该属性的非 jQuery 对象通过验证。我相信在原型中检查该属性可以改善情况。也许你应该在你的答案中加入这个!我认为这里没有其他答案提到这种可能性 :) - Gui Prá
1
obj.__proto__.jquery 而不是 obj.constructor.prototype.jquery 不就够了吗?简短明了 :) - Axel
1
@Axel 是的,它也可以工作 :). 我使用了 constructor.prototype,因为 obj 应该是构造函数 jQuery 的一个实例。另一方面,__proto__ 对于任何类型的对象都是可用的。 - jherax

5

如果想在没有安装jQuery的情况下判断一个对象是否为jQuery对象,可以使用以下代码:

function isJQuery(obj) {
  // All jQuery objects have an attribute that contains the jQuery version.
  return typeof obj === "object" && obj != null && obj.jquery != null;
}

&& obj && 是用来检查 obj 是否不为 null 的,因为 typeof null 也返回 'object'。它也可以是 obj !== null,但这样也是正确的。 - Nuno Rafael Figueiredo
@NunoRafaelFigueiredo 更新了我七年前的答案,考虑到了你的评论,并改进了与“obj!= null”进行比较,因为它还排除了“undefined”。 - Karl.S

4
然而,在 jQuery 中还有一种检查对象的方式。
jQuery.type(a); //this returns type of variable.

我已经制作了一个示例来理解这些内容,jsfiddle链接


3
return el instanceof jQuery ? el.size() > 0 : (el && el.tagName);

为了检查 DOM 元素,最好使用 nodeType 属性,并确保返回一个布尔值,您可以使用双重否定 !!(el && el.nodeType) - jherax

2
你可以通过 jquery 属性检查对象是否由 JQuery 生成:
myObject.jquery // 3.3.1

=> 如果由JQuery产生的对象,请返回JQuery版本号。 => 否则,返回undefined


-9
var elArray = [];
var elObjeto = {};

elArray.constructor == Array //TRUE
elArray.constructor == Object//TALSE

elObjeto.constructor == Array//FALSE
elObjeto.constructor == Object//TRUE

12
不附带说明的代码转储很少有用。请考虑在你的答案中添加一些上下文信息。 - Chris

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接