何时使用Vanilla JavaScript与jQuery?


238

我注意到在监视/尝试回答常见的jQuery问题时,有一些使用javascript而不是jQuery的实践实际上使您可以编写更少的代码并且做得 ...相当。并且还可能产生性能优势。

一个具体的例子

$(this)this

在点击事件中引用点击的对象ID

jQuery的

$(this).attr("id");

Java脚本

this.id;

还有其他类似的常规做法吗?无需将jQuery混用就可以更轻松地完成某些Javascript操作的地方。还是这是罕见的情况?(实际上是需要更多代码的jQuery“快捷方式”)

编辑:虽然我很欣赏有关jQuery与普通javascript性能的答案,但实际上我正在寻找更多定量的答案。 使用jQuery时,使用普通javascript而不是使用javascript可能会更好(可读性/紧凑性)的实例$()。除了我在原始问题中给出的示例。


我不确定我是否理解这个问题。您是在寻找有关使用库代码的优点的意见,还是在寻找其他类似于jQuery的非jQuery跨浏览器兼容技术this.id
user113716 2011年

1
从答案看来,似乎每个人都将这个问题视为哲学上的问题,正如我所希望的那样,它是非常定量的,因此几乎可以像我概述的那样列出一系列常见的(不当的)做法。
jondavidjohn 2011年


Answers:


207
  • this.id (如你所知)
  • this.value(在大多数输入类型上。只有当我<select>没有value在其<option>元素上设置属性或在Safari中输入广播时,我才知道是IE 。)
  • this.className 获取或设置整个“类”属性
  • this.selectedIndex针对<select>以获取选定的索引
  • this.options针对<select>以获取<option>元素列表
  • this.text反对<option>以获取其文本内容
  • this.rows反对<table>获取<tr>元素集合
  • this.cells反对a <tr>获得其细胞(td&th)
  • this.parentNode 得到直接父母
  • this.checked获取感谢@Tim Down的检查状态checkbox
  • this.selected获取感谢@Tim Down的选定状态option
  • this.disabled获取感谢@Tim Down的禁用状态input
  • this.readOnly获取感谢@Tim Down的readOnly状态input
  • this.href反对<a>获得它的元素href
  • this.hostname针对<a>元素以获取其域href
  • this.pathname针对<a>元素以获取其路径href
  • this.search针对<a>元素以获取其查询字符串href
  • this.src 针对有效的元素 src

...我想你应该已经明白了。

有时性能至关重要。就像您多次执行循环中的某项操作一样,您可能想抛弃jQuery。

通常,您可以替换:

$(el).attr('someName');

与:

上面的措词不好。getAttribute不是替代品,但是它确实检索了从服务器发送的属性的值,并且它的对应属性将对其setAttribute进行设置。在某些情况下是必需的。

下面的句子涵盖了它。请参阅此答案以获得更好的治疗。

el.getAttribute('someName');

...以便直接访问属性。请注意,属性与属性不同(尽管它们有时会相互镜像)。当然也有setAttribute

假设您遇到这样一种情况,即收到了一个页面,您需要在其中解开特定类型的所有标签。jQuery简短易行:

$('span').unwrap();  // unwrap all span elements

但是,如果有很多,您可能需要做一些本地的DOM API:

var spans = document.getElementsByTagName('span');

while( spans[0] ) {
    var parent = spans[0].parentNode;
    while( spans[0].firstChild ) {
        parent.insertBefore( spans[0].firstChild, spans[0]);
    }
    parent.removeChild( spans[0] );
}

这段代码很短,比jQuery版本性能更好,并且可以很容易地在您的个人库中变成可重用的函数。

似乎while由于的缘故,我与外部之间存在无限循环while(spans[0]),但是由于我们正在处理“活动列表”,所以在执行时它会更新parent.removeChild(span[0]);。这是一个非常漂亮的功能,当我们使用数组(或类似数组的对象)时,我们会错过它。


2
很好...因此大多数情况下,它都围绕此关键字而不必要地被包装到jQuery对象中。
jondavidjohn 2011年

1
@jondavidjohn:好吧,在某些情况下有一些不错的修复程序,例如在某些情况this.value下有一些浏览器怪癖。这完全取决于您的需要。如果没有jQuery,有很多不错的技术很容易实现,特别是在性能至关重要的情况下。我会尝试考虑更多。
user113716 2011年

3
我本打算写一个答案,但我会为您添加建议。通常,attr()被过度使用。如果您只处理一个元素,那么您几乎不需要attr()。我最喜欢的两个内容是checked对复选框属性的困惑(围绕那个复选框的各种神秘咒语$(this).attr("checked", "checked")$(this).is(":checked")等等)以及类似地元素的selected属性<option>
蒂姆·唐

1
Aaargh,@ patrick,没有:您推荐了getAttribute()您几乎永远不需要它:它在IE中已损坏,并不总是反映当前状态,这也不是jQuery要做的。只需使用属性。stackoverflow.com/questions/4456231/...
蒂姆向下

1
我使用JS已有很长时间了,我对className,thx一无所知。
IAdapter 2011年

60

正确的答案是,当您使用jQuery而不是“普通的”本机JavaScript时,您将始终承受性能损失。那是因为jQuery是JavaScript库。它不是一些新奇的JavaScript版本。

jQuery之所以强大,是因为它使某些事情在跨浏览器的情况下过于繁琐(AJAX是最好的示例之一),并消除了众多可用浏览器之间的不一致,并提供了一致的API。它还可以轻松地促进链接,隐式迭代等概念,以简化一起处理元素组的工作。

学习jQuery不能代替学习JavaScript。您应该在后者中拥有牢固的基础,以便您充分了解了解前者使您更轻松的事情。

-编辑以包含评论-

由于评论很快指出了这一点(我同意100%),因此上述声明是指基准测试代码。一个“本机” JavaScript解决方案(假设它写得很好)将胜过几乎在每种情况下都能完成相同任务的jQuery解决方案(我很乐意看到一个例子)。jQuery确实加快了开发时间,这是一个很大的好处,我并不是想淡化它。它促进了易于阅读,易于遵循的代码,这超出了某些开发人员自己创建的能力。

依我之见,答案取决于您要达到的目标。根据我对性能优势的引用,如果您认为自己正在以最快的速度离开应用程序,那么每次调用jQuery都会带来开销$()。如果您要提高可读性,一致性,跨浏览器兼容性等,那么肯定有理由偏爱jQuery,而不是“本机” JavaScript。


8
我很乐意看到jQuery可以胜过纯JS实现的情况的示例。无论您做什么,如果使用的是jQuery(或与此有关的任何其他库),都将不可避免地产生函数开销。没有任何方法可以消除调用产生的(尽管)较小的开销$()。如果您不拨打电话,则可以节省时间。
gddc 2011年

16
写得不好的自制解决方案可能会更慢。jQuery团队已在软件包中执行了一些高效的JavaScript。请参阅@Freelancer的答案。
斯蒂芬

3
写得不好的解决方案将永远是写得不好的解决方案,这不是语言的错。如果考虑周到,该库将产生“本机”函数可以避免的开销,这一事实并没有改变。
gddc 2011年

11
@gddc我认为最好的例子,其中jQuery的“性能优于”(读基准箱外)纯JS是在削减开发时间(这是一个巨大的价值的业务明智),并简化实验

13
您编写的所有内容都是正确的,但是您忽略了上面的@Ben注释。jQuery使开发人员更快,更强大。请看我多年前编写并大量使用的KillClass()实现。你知道吗?在某些情况下,它是的。不良代码是不良代码,错误代码是错误代码,但是使用jQuery通常会使开发人员编写更好,更正确的代码。大多数时候,计算机足够快。需要帮助的是开发人员。
Phrogz 2011年

38

有一个名为...的框架,哦,猜猜是什么?Vanilla JS。希望您能开玩笑...:D它牺牲了代码的可读性以提高性能...相比之下,jQuery您可以看到,检索DOM元素的速度快了ID将近35倍。:)

因此,如果要提高性能,最好尝试使用Vanilla JS并得出自己的结论。也许您不会在密集代码(例如for循环内)中挂起JavaScript来挂起浏览器的GUI /锁定UI线程。

Vanilla JS是一个快速,轻量级的跨平台框架,用于构建功能强大的JavaScript应用程序。

在他们的首页上有一些性能比较:

在此处输入图片说明


1
@Leniel Macaferi噢,我很喜欢这个答案!我没有意识到香草和其他框架之间的性能会产生如此大的改变!无论如何,名人堂都是这个答案!!PS:您是否也建立了网站?
史蒂夫,

17

已经有一个可以接受的答案,但是我相信在此直接键入的答案在其实际上具有跨浏览器支持保证的本机javascript方法/属性列表中可能并不全面。为此,我可以将您重定向到quirksmode:

http://www.quirksmode.org/compatibility.html

它可能是最有效的清单,列出了在任何地方的浏览器中什么有效,什么无效。请特别注意DOM部分。阅读内容很多,但重点不是要全部阅读而是将其用作参考。

当我开始认真地编写Web应用程序时,我打印了所有DOM表并将它们挂在墙上,以便我一眼就知道什么是安全使用的和需要黑客攻击的。这些天,我只是用谷歌搜索类似的东西quirksmode parentNode compatibility

像其他任何事物一样,判断主要取决于经验。我真的不建议您阅读整个网站并记住所有问题以弄清楚何时使用jQuery和何时使用纯JS。请注意列表。搜索起来很容易。随着时间的流逝,您将逐渐了解何时首选纯JS。


PS:PPK(该网站的作者)也有一本非常不错的书,我建议阅读


14

什么时候:

  1. 您知道您正在做什么的跨浏览器坚定支持,并且
  2. 键入的代码并不多,并且
  3. 它的可读性不是很差,并且
  4. 您有理由相信jQuery不会基于浏览器选择不同的实现来获得更好的性能,然后:

使用JavaScript。否则,请使用jQuery(如果可以)。

编辑:此答案适用于选择整体使用jQuery而不是使用它,以及选择是否在jQuery中使用香草JS。选择attr('id').id倾向于JS,而选择removeClass('foo').className = .className.replace( new Regexp("(?:^|\\s+)"+foo+"(?:\\s+|$)",'g'), '' )倾向于jQuery。


3
我认为OP打算使用jQuery,但想知道他的jQuery方法中何时何地使用本机JavaScript。
斯蒂芬,

.classList.remove('foo')似乎在较新的浏览器中可以正常工作
Tyilo

3
@Tyilo classList.remove是IE9中未实现的HTML5 ClassList API的一部分,例如caniuse.com/#feat=classlist
corbacho 2012年

13

其他人的答案集中在“ jQuery vs. Plain JS”这一广泛的问题上。从您的OP来看,我认为您只是想知道,如果您已经选择使用jQuery,那么何时使用Vanilla JS更好。您的示例是何时使用Vanilla JS的完美示例:

$(this).attr('id');

在以下方面既慢又(我认为)可读性差:

this.id

速度较慢,因为您必须旋转一个新的JS对象才能以jQuery的方式检索该属性。现在,如果您打算用来$(this)执行其他操作,那么一定要将该jQuery对象存储在变量中并对其进行操作。但是,在很多情况下,我只需要元素中的属性(如idsrc)。

还有其他类似的常规做法吗?无需将jQuery混用就可以更轻松地完成某些Javascript操作的地方。还是这是罕见的情况?(实际上是需要更多代码的jQuery“快捷方式”)

我认为最常见的情况是您在帖子中描述的情况;人们$(this)不必要地将其包装在jQuery对象中。我最常通过idvalue(而不是使用$(this).val())看到这种情况。

编辑: 是一篇文章,解释为什么在这种attr()情况下使用jQuery 速度较慢。告白:从标记Wiki上窃取了,但是我认为这个问题值得一提。

再次编辑:考虑到直接访问属性的可读性/性能影响,我想说一个好的经验法则是尽可能尝试使用this.<attributename>。在某些情况下,由于浏览器不一致,这种方法将无法正常工作,但是最好先尝试一下,然后在无效的情况下使用jQuery。


呵呵,感谢您阅读问题;)...所以从广义上讲这是例外吗?
jondavidjohn 2011年

@jondavidjohn:老实说,我很犹豫打那个电话。我认为是的,由于跨浏览器的问题,使用jQuery通常对您有利。还有其他示例,例如this.style.display = 'none'。比那更好$(this).hide()吗?我认为后者更具可读性,但前者可能更快。进行一些实验以查看某些动作是否可以在没有jQuery的浏览器中运行并没有什么害处-这通常是在将元素包装到jQuery对象中以执行操作之前所做的事情。
Andrew Whitaker

10

如果您最关心的是性能,那么您的主要例子就是打钉子。恕我直言,不必要或多余地调用jQuery是性能降低的第二个主要原因(第一个是DOM遍历不佳)。

它并不是您要查找的内容的真正示例,但我经常看到这一点,因此值得一提:加快jQuery脚本性能的最佳方法之一是缓存jQuery对象和/或使用链接:

// poor
$(this).animate({'opacity':'0'}, function() { $(this).remove(); });

// excellent
var element = $(this);
element.animate({'opacity':'0'}, function() { element.remove(); });

// poor
$('.something').load('url');
$('.something').show();

// excellent
var something = $('#container').children('p.something');
something.load('url').show();

有趣的是... var实例和动作的这种分离是否真的导致处理性能的提高?或只是允许动作自行执行(我
想让

1
当然,这肯定会提高性能,但前提是您重新使用所选元素。因此,在最后一种情况下var something,我实际上不需要缓存jQuery对象(因为我使用了链接),但是无论如何我还是出于习惯。
斯蒂芬

2
另一方面,采用相同的示例。调用$('.something')两次意味着jQuery必须遍历DOM 两次,以使用该选择器查找所有元素。
斯蒂芬

2
在第一个示例的情况下,缓存$(this)减少了对jQuery函数的调用。这将使您在循环场景中获得最大收益。
斯蒂芬

2
@Alnitak请注意,element它等于$(this)。那不包含多个元素。
斯蒂芬

8

我发现JS和JQ之间肯定存在重叠。您显示的代码就是一个很好的例子。坦率地说,在JS上使用JQ的最佳原因仅仅是浏览器兼容性。我总是倾向于JQ,即使我可以在JS中完成某些工作。


8
如果JQuery是JavaScript,是否存在任何重叠都将是一个奇迹。
simon

6

这是我的个人观点,但是由于jQuery仍然是JavaScript,因此我认为从理论上讲它无法比Vanilla JS表现更好。

但是实际上,它的性能可能比手写JS好,因为一个人的手写代码可能不如jQuery高效。

底线-对于较小的东西,我倾向于使用香草JS,对于我喜欢使用jQuery而不是重新发明轮子的JS密集型项目-它也更具生产力。


1
有许多示例优于库JS。事实证明,许多JS内置的原型方法都写得不好。
学习统计数据,例如

3

this作为DOM元素的第一个答案的实时属性列表非常完整。

您可能还会发现认识其他人也很有趣。

当这是文件时:

  • this.forms获取HTMLCollection当前的文档表格,
  • this.anchors得到的HTMLCollection所有的HTMLAnchorElementsname被设定,
  • this.links得到的HTMLCollection所有的HTMLAnchorElement与S href是一套,
  • this.images得到HTMLCollection所有HTMLImageElement
  • 和不赞成使用的小程序一样 this.applets

与您合作时document.formsdocument.forms[formNameOrId]将获得如此命名或标识的表格。

如果是这种形式:

  • this[inputNameOrId] 获得如此命名或标识的字段

当这是表单字段时:

  • this.type 获取字段类型

在学习jQuery选择器时,我们经常跳过学习已经存在的HTML元素属性,这些属性是如此之快地访问。


您提到的属性在DOM Level 2 HTML规范中定义,并得到广泛支持。document.embeds并且document.plugins得到广泛支持(DOM 0)。document.scripts也是一个方便的集合,在HTML5规范中定义,并且受到广泛支持(和Firefox 9+)。
Rob W

@Robw因此,列表现在可能是完整的,并且绝对有用且快速。谢谢;)
lib3d

2

和往常一样,我来晚了。

并不是让我决定使用jQuery的额外功能是如此吸引人。毕竟没有什么可以阻止您编写自己的函数。

事实是,在修改DOM以避免内存泄漏时有很多技巧需要学习(我在谈论IE)。拥有一个能够为我解决所有此类问题的中央资源,由比我以前要好得多的JS编码人员编写,并且不断地对其进行审查,修订和测试是令人敬畏的。

我猜想这种情况属于跨浏览器的support / abstraction参数。

当然,jQuery在需要时不排除使用直接JS。我总是觉得两者似乎无缝地协同工作。

当然,如果jQuery不支持您的浏览器,或者您支持的是低端环境(旧手机?),那么大的.js文件可能是个问题。还记得jQuery曾经很小的时候吗?

但是通常情况下,性能差异不是问题。它只必须足够快。随着每秒千兆赫的CPU周期浪费,我更关心编码器的性能,这是唯一的开发资源,每18个月的功耗不会增加一倍。

就是说,我目前正在研究可访问性问题,显然.innerHTML对此有些反对。jQuery当然依赖于.innerHTML,所以现在我正在寻找一个框架,该框架将取决于所允许的有些乏味的方法。我可以想象这样的框架会比jQuery慢,但是只要它运行良好,我就会很高兴。


2

这是一个非技术性的答案-许多工作可能不允许使用某些库,例如jQuery。

事实上,事实上,Google不允许在其任何代码中使用jQuery(也不是React,因为它是Facebook拥有的),在面试官说“抱歉,但是您不能使用jQuery时,您可能还不知道它,否则您可能无法使用它XYZ公司批准的清单”。Vanilla JavaScript绝对可以在任何地方,每次都能工作,并且永远不会给您这个问题。如果您依赖库,则可以快速而轻松地工作,但是却失去了普遍性。

另外,谈到面试,另一个缺点是,如果您说您需要在代码测验中使用库来解决JavaScript问题,就会遇到问题,就像您实际上并不了解问题一样,这看起来有点不好。而如果您使用原始的JavaScript来解决它,则说明您真正理解并可以解决他们摆在您面前的任何问题。


1

$(this) 与...不同 this

通过使用$(this),可以确保将jQuery原型传递到对象上。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.