【问题标题】:When to use Vanilla JavaScript vs. jQuery?何时使用 Vanilla JavaScript 与 jQuery?
【发布时间】:2011-06-06 19:40:15
【问题描述】:

我在监控/尝试回答常见的 jQuery 问题时注意到,有一些使用 javascript 而不是 jQuery 的做法,实际上使您能够少写并做 ...数量。并且还可能产生性能优势。

一个具体的例子

$(this)this

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

jQuery

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

Javascript

this.id;

还有其他类似的常见做法吗?可以更轻松地完成某些 Javascript 操作,而无需将 jQuery 混入其中。或者这是一个罕见的案例? (实际上需要更多代码的 jQuery“快捷方式”)

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

【问题讨论】:

标签: javascript jquery performance


【解决方案1】:
  • this.id(如你所知)
  • this.value(在大多数输入类型上。当<select>value 没有在其<option> 元素上设置value 属性或Safari 中的无线电输入时,我知道的唯一问题是IE。)
  • this.className 获取或设置整个“类”属性
  • this.selectedIndex 对抗 <select> 以获取所选索引
  • this.options<select> 对比以获取 <option> 元素列表
  • this.text 对抗 <option> 以获取其文本内容
  • this.rows<table> 对比以获取 <tr> 元素的集合
  • this.cells 对抗 <tr> 以获取其单元格(td & th)
  • this.parentNode 获得直系父母
  • this.checked 获取 checkbox Thanks @Tim Down 的选中状态
  • this.selected 获取option 的选定状态@Thanks @Tim Down
  • this.disabled 获取 input 的禁用状态 Thanks @Tim Down
  • this.readOnly 获取input 的只读状态@ Thanks @Tim Down
  • 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 将设置它。在某些情况下是必需的。

下面的句子涵盖了它。 See this answer 以获得更好的治疗。

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(spans[0]),我似乎与外部while 有一个无限循环,但因为我们正在处理“实时列表”,所以当我们执行parent.removeChild(span[0]); 时它会更新。这是我们在使用 Array(或类似 Array 的对象)时错过的一个非常漂亮的功能。

【讨论】:

  • nice...所以它主要围绕 this 关键字不必要地被包装到一个 jQuery 对象中。
  • @jondavidjohn:嗯,在某些情况下有一些很好的修复,比如this.value,在某些情况下会有一些浏览器怪癖。这一切都取决于您的需要。有很多不错的技术在没有 jQuery 的情况下很容易实现,尤其是在性能至关重要的情况下。我会试着想更多。
  • 我正要写一个答案,但我会为你添加建议。通常,attr() 被大量过度使用。如果您只处理一个元素,那么您将很少需要attr()。我最喜欢的两个是对复选框的checked 属性的混淆(围绕该属性的各种神秘咒语:$(this).attr("checked", "checked")$(this).is(":checked") 等)和<option> 元素的selected 属性类似。跨度>
  • Aaargh,@patrick,noooo:你推荐了getAttribute()你几乎从不需要它:它在 IE 中被破坏了,并不总是反映当前状态,而且它也不是 jQuery 所做的。只需使用属性。 stackoverflow.com/questions/4456231/…
  • 我用JS这么久了还不知道className,谢谢。
【解决方案2】:

正确的答案是,在使用 jQuery 而不是“普通的旧”原生 JavaScript 时,您将总是受到性能损失。那是因为 jQuery 是一个 JavaScript 库。它不是什么花哨的 JavaScript 新版本。

jQuery 之所以强大,是因为它在跨浏览器的情况下做了一些过于繁琐的事情(AJAX 是最好的例子之一),并平滑了无数可用浏览器之间的不一致,并提供了一致的 API .它还可以轻松促进链接、隐含迭代等概念,以简化一起处理元素组。

学习 jQuery 并不能替代学习 JavaScript。您应该在后者方面有坚实的基础,这样您才能充分理解了解前者对您的帮助。

-- 编辑以包含 cmets--

由于 cmets 很快指出(我 100% 同意),上述陈述指的是基准测试代码。一个“本机”JavaScript 解决方案(假设它写得很好)将胜过一个 jQuery 解决方案,它几乎在所有情况下都完成了同样的事情(我很乐意看到一个例子)。 jQuery 确实加快了开发时间,这是一个我无意淡化的显着优势。它有助于易于阅读、易于遵循的代码,这超出了一些开发人员自己创建的能力。

那么,在我看来,答案取决于您要达到的目标。如果,正如我根据您对性能优势的引用所推测的那样,您追求的是应用程序的最佳速度,那么每次调用 $() 时,使用 jQuery 都会引入开销。如果您追求可读性、一致性、跨浏览器兼容性等,那么肯定有理由偏爱 jQuery 而不是“原生”JavaScript。

【讨论】:

  • 我很想看到一个例子,说明 jQuery 可以胜过纯 JS 中的实现。无论您做什么,如果您使用 jQuery(或任何其他库),您将不可避免地产生函数开销。没有办法摆脱调用$() 产生的(尽管)小开销。如果您不拨打电话,您可以节省时间。
  • 一个写得不好的自制解决方案可能会更慢。 jQuery 团队在包中执行了一些高效的 JavaScript。请参阅@Freelancer 的回答。
  • 一个写得不好的解决方案永远是一个写得不好的解决方案,这不是语言的错。它不会改变库会产生开销的事实,如果经过深思熟虑,“本机”函数可以避免。
  • @g.d.d.c.我认为 jQuery “优于”(在基准测试框之外阅读)纯 JS 的最佳示例是减少开发时间(这在业务方面具有巨大价值)并简化实验
  • 您所写的所有内容都是真实的,但您忽略了上面@Ben 指出的内容。 jQuery 使 developer 更快、更健壮。请参阅我多年前写的并大量使用的this KillClass() implementation。你知道吗?对于某些边缘情况,它损坏。糟糕的代码就是糟糕的代码,错误的代码就是错误的代码,但是使用 jQuery 往往会让开发者写出更好、更正确的代码。大多数时候,计算机足够快。需要帮助的是开发人员。
【解决方案3】:

有一个框架叫做...哦,你猜怎么着? Vanilla JS。希望你能听懂这个笑话... :D 它牺牲了代码的易读性来提高性能... 将其与下面的jQuery 进行比较,您可以看到通过ID 检索DOM 元素几乎是35X快点。 :)

因此,如果您想要性能,您最好尝试 Vanilla JS 并得出自己的结论。也许您不会在像 for 循环那样密集的代码期间遇到 JavaScript 挂起浏览器的 GUI/锁定 UI 线程。

Vanilla JS 是一个快速、轻量级、跨平台的框架,用于 构建令人难以置信的强大 JavaScript 应用程序。

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

【讨论】:

  • @Leniel Macaferi 哦,伙计,我喜欢这个答案!我没有意识到香草和其他框架之间的性能可以产生如此大的差异!无论如何,这个答案的名人堂! P.S:你也做了这个网站吗?
【解决方案4】:

已经有一个公认的答案,但我相信这里直接输入的答案在它的原生 javascript 方法/属性列表中是全面的,实际上保证了跨浏览器支持。为此,我可以将您重定向到 quirksmode:

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

这可能是最全面的列表,其中列出了在任何地方的浏览器上哪些有效,哪些无效。特别注意 DOM 部分。阅读量很大,但重点不是全部阅读,而是作为参考。

当我开始认真编写 Web 应用程序时,我打印出所有的 DOM 表并将它们挂在墙上,这样我一眼就知道什么是安全的,什么需要 hack。这些天,当我有疑问时,我只是在谷歌上搜索quirksmode parentNode compatibility 之类的东西。

与其他任何事情一样,判断主要是经验问题。我真的不建议您阅读整个站点并记住所有问题以弄清楚何时使用 jQuery 以及何时使用纯 JS。请注意列表。搜索很容易。随着时间的推移,你会产生一种直觉,知道什么时候更喜欢纯 JS。


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

【讨论】:

    【解决方案5】:

    时间:

    1. 您知道对于您正在做的事情有坚定的跨浏览器支持,并且
    2. 需要输入的代码并不多,而且
    3. 它的可读性并没有明显降低,并且
    4. 您有理由相信 jQuery 不会根据浏览器选择不同的实现来获得更好的性能,那么:

    使用 JavaScript。否则使用 jQuery(如果可以的话)。

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

    【讨论】:

    • 我认为 OP 打算使用 jQuery,但想知道在他的 jQuery 方法中何时何地使用原生 JavaScript。
    • .classList.remove('foo') 在较新的浏览器中似乎可以正常工作
    • @Tyilo classList.remove 是在 IE9 中未实现的 HTML5 ClassList API 的一部分,例如 caniuse.com/#feat=classlist
    【解决方案6】:

    其他人的回答集中在“jQuery 与普通 JS”这个广泛的问题上。从你的 OP 来看,我想你只是想知道如果你已经选择使用 jQuery,什么时候使用 vanilla JS 更好。您的示例是何时应该使用 vanilla JS 的完美示例:

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

    与以下相比,速度较慢且(在我看来)可读性较差:

    this.id.

    它比较慢,因为您必须启动一个新的 JS 对象才能以 jQuery 方式检索属性。现在,如果您要使用$(this) 执行其他操作,那么无论如何,将该jQuery 对象存储在一个变量中并使用它进行操作。但是,我遇到过很多只需要元素属性的情况(例如idsrc)。

    还有其他常见的做法吗 像这样?某些 Javascript 操作可以完成 更简单,无需将 jQuery 引入 混合。或者这是一个罕见的案例? (一个 jQuery“快捷方式”实际上需要 更多代码)

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

    编辑:Here 的文章解释了为什么attr() 情况下使用 jQuery 速度较慢。忏悔:从标签wiki偷来的,但我认为这个问题值得一提。

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

    【讨论】:

    • 哈哈,感谢您阅读这个问题 ;) ...所以这是更广泛的例外?
    • @jondavidjohn:老实说,我很犹豫要不要打这个电话。我认为是的,由于跨浏览器的考虑,使用 jQuery 通常对您有利。还有其他示例,例如this.style.display = 'none'。这比$(this).hide()好吗?我认为后者更具可读性,但前者可能更快。自己做一些实验来看看某些操作是否可以在没有 jQuery 的浏览器中工作并没有什么坏处——这通常是我在将元素包装到 jQuery 对象中以执行操作之前所做的。
    【解决方案7】:

    如果您最关心的是性能,那么您的主要示例就一针见血。恕我直言,不必要或冗余地调用 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 实例化和动作的分离实际上会带来处理性能的提升吗?或者只是允许动作自行执行(我猜想减少它的负担......)
    • 它肯定会导致性能提升,但前提是您重新使用选定的元素。所以,在最后一种情况var something 中,我真的不需要缓存 jQuery 对象(因为我使用了链接),但我还是出于习惯这样做了。
    • 另一方面,同样的例子。调用 $('.something') 两次意味着 jQuery 必须遍历 DOM 两次 以查找具有该选择器的所有元素。
    • 在第一个示例中,缓存$(this) 减少了对 jQuery 函数的调用。这将使您在循环场景中获得最大收益。
    • @Alnitak 注意element 等于$(this)。不包含多个元素。
    【解决方案8】:

    我发现 JS 和 JQ 之间肯定有重叠。您展示的代码就是一个很好的例子。坦率地说,使用 JQ 而不是 JS 的最佳理由仅仅是浏览器兼容性。我总是倾向于 JQ,即使我可以在 JS 中完成一些事情。

    【讨论】:

    • 如果没有任何重叠会很奇怪,因为 JQuery 是 JavaScript。
    【解决方案9】:

    这是我个人的看法,但无论如何 jQuery 是 JavaScript,我认为理论上它的性能无法比 vanilla JS 更好。

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

    底线 - 对于较小的东西我倾向于使用 vanilla JS,对于 JS 密集型项目我喜欢使用 jQuery 而不是重新发明轮子 - 它也更有效率。

    【讨论】:

    • 有很多例子表明库的性能优于原生 JS。事实证明,很多 JS 的内置原型方法都写得很糟糕。
    【解决方案10】:

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

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

    当这是文件时:

    • this.forms 获取当前文档表单的HTMLCollection
    • this.anchors 获取所有 HTMLAnchorElements 中的 HTMLCollection 并设置了 name
    • this.links 获取所有 HTMLAnchorElements 中的 HTMLCollection 并设置了 href
    • this.images 获取所有HTMLImageElements 中的HTMLCollection
    • 与已弃用的小程序相同,如 this.applets

    当您使用document.forms 时,document.forms[formNameOrId] 会获得如此命名或标识的表单。

    当这是一个表格时:

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

    当这是表单域时:

    • this.type获取字段类型

    在学习 jQuery 选择器时,我们经常跳过学习已经存在的 HTML 元素属性,这些属性访问起来非常快。

    【讨论】:

    • 您提到的属性在DOM Level 2 HTML specification 中定义,并得到广泛支持。 document.embedsdocument.plugins 也得到广泛支持 (DOM 0)。 document.scripts 也是一个方便的集合,在HTML5 specification 中定义,并得到广泛支持(和Firefox 9+)。
    • @Robw 所以这个列表现在可能是完整的,而且绝对有用且快速。谢谢;)
    【解决方案11】:

    像往常一样,我参加这个聚会迟到了。

    让我决定使用 jQuery 的并不是额外的功能,因为它很有吸引力。毕竟没有什么能阻止你编写自己的函数。

    事实上,在修改 DOM 以避免内存泄漏时需要学习很多技巧(我说的是 IE)。拥有一个为我管理所有这些问题的中心资源,由比我优秀得多的 JS 编码人员编写,并且不断审查、修订和测试,真是天赐良机。

    我猜这属于跨浏览器支持/抽象参数。

    当然,jQuery 并不排除在您需要时直接使用 JS。我一直觉得这两者似乎可以无缝地协同工作。

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

    但通常性能差异不是问题。它只需要足够快。由于每秒都会浪费千兆赫的 CPU 周期,我更关心我的编码器的性能,这是唯一不会每 18 个月功率翻倍的开发资源。

    也就是说,我目前正在研究可访问性问题,显然 .innerHTML 对此有点不妥。 jQuery 当然依赖于.innerHTML,所以现在我正在寻找一个框架,该框架将依赖于允许的有些繁琐的方法。而且我可以想象这样一个框架会比jQuery运行得慢,但只要它表现得足够好,我会很高兴。

    【讨论】:

      【解决方案12】:

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

      事实上,事实上,Google 不允许在他们的任何代码中使用 jQuery(React 也不允许,因为它归 Facebook 所有),直到面试官说“对不起,但你不能使用 jQuery,它不在 XYZ 公司的批准名单上”。 Vanilla JavaScript 绝对适用于任何地方,任何时候,并且永远不会给你这个问题。如果你依赖库,是的,你会得到速度和轻松,但你会失去普遍性。

      另外,说到面试,另一个缺点是,如果你在代码测验中说你需要使用库来解决 JavaScript 问题,你会觉得你并不真正理解这个问题,这看起来有点糟糕.然而,如果你用原始的原生 JavaScript 解决它,它表明你真正理解并且可以解决他们摆在你面前的任何问题的每一部分。

      【讨论】:

        【解决方案13】:

        $(this)this 不同:

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

        【讨论】:

          猜你喜欢
          • 2020-04-18
          • 1970-01-01
          • 1970-01-01
          • 2023-01-25
          • 1970-01-01
          • 2018-12-20
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多