[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"project-3165":3},{"id":4,"name":5,"fullName":6,"owner":7,"repo":5,"description":8,"homepage":9,"htmlUrl":10,"language":11,"languages":10,"totalLinesOfCode":10,"stars":12,"forks":13,"watchers":14,"openIssues":15,"contributorsCount":16,"subscribersCount":16,"size":16,"stars1d":16,"stars7d":16,"stars30d":17,"stars90d":16,"forks30d":16,"starsTrendScore":16,"compositeScore":18,"rankGlobal":10,"rankLanguage":10,"license":19,"archived":20,"fork":20,"defaultBranch":21,"hasWiki":22,"hasPages":20,"topics":23,"createdAt":10,"pushedAt":10,"updatedAt":24,"readmeContent":25,"aiSummary":26,"trendingCount":16,"starSnapshotCount":16,"syncStatus":27,"lastSyncTime":28,"discoverSource":29},3165,"You-Dont-Need-jQuery","camsong\u002FYou-Dont-Need-jQuery","camsong","Examples of how to do query, style, dom, ajax, event etc like jQuery with plain javascript.","",null,"JavaScript",20161,1718,518,3,0,1,69.81,"MIT License",false,"master",true,[],"2026-06-12 04:00:16","## You (Might) Don't Need jQuery\n\nFrontend environments evolve rapidly nowadays and modern browsers have already implemented a great deal of DOM\u002FBOM APIs which are good enough for production use. We don't have to learn jQuery from scratch for DOM manipulation or event handling. In the meantime, thanks to the spread of frontend libraries such as React, Angular and Vue, manipulating the DOM directly becomes anti-pattern, so that jQuery usage has never been less important. This project summarizes most of the alternatives in native Javascript implementation to jQuery methods, with IE 10+ support.\n\nℹ️ Notice: \n1. jQuery is still a great library and has many valid use cases. Don’t migrate away if you don’t want to!\n2. The alternatives are not completely equivalent in all scenarios, and it is recommended that you test it before using it.\n\n## Table of Contents\n\n1. [Translations](#translations)\n1. [Query Selector](#query-selector)\n1. [CSS & Style](#css--style)\n1. [DOM Manipulation](#dom-manipulation)\n1. [Ajax](#ajax)\n1. [Events](#events)\n1. [Utilities](#utilities)\n1. [Promises](#promises)\n1. [Animation](#animation)\n1. [Alternatives](#alternatives)\n1. [Browser Support](#browser-support)\n\n## Translations\n\n* [한국어](.\u002FREADME.ko-KR.md)\n* [正體中文](.\u002FREADME.zh-TW.md)\n* [简体中文](.\u002FREADME.zh-CN.md)\n* [Bahasa Melayu](.\u002FREADME-my.md)\n* [Bahasa Indonesia](.\u002FREADME-id.md)\n* [Português(PT-BR)](.\u002FREADME.pt-BR.md)\n* [Tiếng Việt Nam](.\u002FREADME-vi.md)\n* [Español](.\u002FREADME-es.md)\n* [Русский](.\u002FREADME-ru.md)\n* [Кыргызча](.\u002FREADME-kg.md)\n* [Türkçe](.\u002FREADME-tr.md)\n* [Italiano](.\u002FREADME-it.md)\n* [Français](.\u002FREADME-fr.md)\n* [日本語](.\u002FREADME-ja.md)\n* [Polski](.\u002FREADME-pl.md)\n\n## Query Selector\n\nIn place of common selectors like class, id or attribute we can use `document.querySelector` or `document.querySelectorAll` for substitution. The differences lie in:\n* `document.querySelector` returns the first matched element\n* `document.querySelectorAll` returns all matched elements as NodeList. It can be converted to Array using `Array.prototype.slice.call(document.querySelectorAll(selector));` or any of the methods outlined in [makeArray](#makeArray)\n* If there are no elements matched, jQuery and `document.querySelectorAll` will return `[]`, whereas `document.querySelector` will return `null`.\n\n> Notice: `document.querySelector` and `document.querySelectorAll` are quite **SLOW**, thus try to use `document.getElementById`, `document.getElementsByClassName` or `document.getElementsByTagName` if you want to get a performance bonus.\n\n- [1.0](#1.0) \u003Ca name='1.0'>\u003C\u002Fa> Query by selector\n\n  ```js\n  \u002F\u002F jQuery\n  $('selector');\n\n  \u002F\u002F Native\n  document.querySelectorAll('selector');\n  ```\n\n- [1.1](#1.1) \u003Ca name='1.1'>\u003C\u002Fa> Query by class\n\n  ```js\n  \u002F\u002F jQuery\n  $('.class');\n\n  \u002F\u002F Native\n  document.querySelectorAll('.class');\n\n  \u002F\u002F or\n  document.getElementsByClassName('class');\n  ```\n\n- [1.2](#1.2) \u003Ca name='1.2'>\u003C\u002Fa> Query by id\n\n  ```js\n  \u002F\u002F jQuery\n  $('#id');\n\n  \u002F\u002F Native\n  document.querySelector('#id');\n\n  \u002F\u002F or\n  document.getElementById('id');\n\n  \u002F\u002F or\n  window['id']\n  ```\n\n- [1.3](#1.3) \u003Ca name='1.3'>\u003C\u002Fa> Query by attribute\n\n  ```js\n  \u002F\u002F jQuery\n  $('a[target=_blank]');\n\n  \u002F\u002F Native\n  document.querySelectorAll('a[target=_blank]');\n  ```\n\n- [1.4](#1.4) \u003Ca name='1.4'>\u003C\u002Fa> Query in descendants\n\n  ```js\n  \u002F\u002F jQuery\n  $el.find('li');\n\n  \u002F\u002F Native\n  el.querySelectorAll('li');\n  ```\n\n- [1.5](#1.5) \u003Ca name='1.5'>\u003C\u002Fa> Sibling\u002FPrevious\u002FNext Elements\n\n  + All siblings\n\n    ```js\n    \u002F\u002F jQuery\n    $el.siblings();\n\n    \u002F\u002F Native - latest, Edge13+\n    [...el.parentNode.children].filter((child) =>\n      child !== el\n    );\n    \u002F\u002F Native (alternative) - latest, Edge13+\n    Array.from(el.parentNode.children).filter((child) =>\n      child !== el\n    );\n    \u002F\u002F Native - IE10+\n    Array.prototype.filter.call(el.parentNode.children, (child) =>\n      child !== el\n    );\n    ```\n\n  + Previous sibling\n\n    ```js\n    \u002F\u002F jQuery\n    $el.prev();\n\n    \u002F\u002F Native\n    el.previousElementSibling;\n    ```\n  + Next sibling\n\n    ```js\n    \u002F\u002F jQuery\n    $el.next();\n\n    \u002F\u002F Native\n    el.nextElementSibling;\n    ```\n\n  + All previous siblings\n\n    ```js\n    \u002F\u002F jQuery (optional filter selector)\n    $el.prevAll($filter);\n\n    \u002F\u002F Native (optional filter function)\n    function getPreviousSiblings(elem, filter) {\n      var sibs = [];\n      while (elem = elem.previousSibling) {\n          if (elem.nodeType === 3) continue; \u002F\u002F ignore text nodes\n          if (!filter || filter(elem)) sibs.push(elem);\n      }\n      return sibs;\n    }\n\n  + All next siblings\n\n    ```js\n    \u002F\u002F jQuery (optional selector filter)\n    $el.nextAll($filter);\n\n    \u002F\u002F Native (optional filter function)\n    function getNextSiblings(elem, filter) {\n            var sibs = [];\n            var nextElem = elem.parentNode.firstChild;\n            do {\n                if (nextElem.nodeType === 3) continue; \u002F\u002F ignore text nodes\n                if (nextElem === elem) continue; \u002F\u002F ignore elem of target\n                if (nextElem === elem.nextElementSibling) {\n                    if (!filter || filter(elem)) {\n                        sibs.push(nextElem);\n                        elem = nextElem;\n                    }\n                }\n            } while(nextElem = nextElem.nextSibling)\n            return sibs;\n        }\n\nAn example of filter function:\n\n```js\nfunction exampleFilter(elem) {\n  switch (elem.nodeName.toUpperCase()) {\n    case 'DIV':\n      return true;\n    case 'SPAN':\n      return true;\n    default:\n      return false;\n  }\n}\n```\n\n- [1.6](#1.6) \u003Ca name='1.6'>\u003C\u002Fa> Closest\n\n  Return the first matched element by provided selector, traversing from current element up through its ancestors in the DOM tree.\n\n  ```js\n  \u002F\u002F jQuery\n  $el.closest(selector);\n\n  \u002F\u002F Native - Only latest, NO IE\n  el.closest(selector);\n\n  \u002F\u002F Native - IE10+\n  function closest(el, selector) {\n    const matchesSelector = el.matches || el.webkitMatchesSelector || el.mozMatchesSelector || el.msMatchesSelector;\n\n    while (el) {\n      if (matchesSelector.call(el, selector)) {\n        return el;\n      } else {\n        el = el.parentElement;\n      }\n    }\n    return null;\n  }\n  ```\n\n- [1.7](#1.7) \u003Ca name='1.7'>\u003C\u002Fa> Parents Until\n\n  Get the ancestors of each element in the current set of matched elements, up to but not including the element matched by the selector, DOM node, or jQuery object.\n\n  ```js\n  \u002F\u002F jQuery\n  $el.parentsUntil(selector, filter);\n\n  \u002F\u002F Native\n  function parentsUntil(el, selector, filter) {\n    const result = [];\n    const matchesSelector = el.matches || el.webkitMatchesSelector || el.mozMatchesSelector || el.msMatchesSelector;\n\n    \u002F\u002F match start from parent\n    el = el.parentElement;\n    while (el && !matchesSelector.call(el, selector)) {\n      if (!filter) {\n        result.push(el);\n      } else {\n        if (matchesSelector.call(el, filter)) {\n          result.push(el);\n        }\n      }\n      el = el.parentElement;\n    }\n    return result;\n  }\n  ```\n\n- [1.8](#1.8) \u003Ca name='1.8'>\u003C\u002Fa> Form\n\n  + Input\u002FTextarea\n\n    ```js\n    \u002F\u002F jQuery\n    $('#my-input').val();\n\n    \u002F\u002F Native\n    document.querySelector('#my-input').value;\n    ```\n\n  + Get index of e.currentTarget between `.radio`\n\n    ```js\n    \u002F\u002F jQuery\n    $('.radio').index(e.currentTarget);\n\n    \u002F\u002F Native\n    Array.from(document.querySelectorAll('.radio')).indexOf(e.currentTarget);\n    or\n    Array.prototype.indexOf.call(document.querySelectorAll('.radio'), e.currentTarget);\n    ```\n\n- [1.9](#1.9) \u003Ca name='1.9'>\u003C\u002Fa> Iframe Contents\n\n  `$('iframe').contents()` returns `contentDocument` for this specific iframe\n\n  + Iframe contents\n\n    ```js\n    \u002F\u002F jQuery\n    $iframe.contents();\n\n    \u002F\u002F Native\n    iframe.contentDocument;\n    ```\n\n  + Iframe Query\n\n    ```js\n    \u002F\u002F jQuery\n    $iframe.contents().find('.css');\n\n    \u002F\u002F Native\n    iframe.contentDocument.querySelectorAll('.css');\n    ```\n\n- [1.10](#1.10) \u003Ca name='1.10'>\u003C\u002Fa> Get body\n\n  ```js\n  \u002F\u002F jQuery\n  $('body');\n\n  \u002F\u002F Native\n  document.body;\n  ```\n\n- [1.11](#1.11) \u003Ca name='1.11'>\u003C\u002Fa> Attribute getter and setter\n\n  + Get an attribute\n\n    ```js\n    \u002F\u002F jQuery\n    $el.attr('foo');\n\n    \u002F\u002F Native\n    el.getAttribute('foo');\n    ```\n  + Set an attribute\n\n    ```js\n    \u002F\u002F jQuery\n    $el.attr('foo', 'bar');\n\n    \u002F\u002F Native\n    el.setAttribute('foo', 'bar');\n    ```\n\n  + Get a `data-` attribute\n\n    ```js\n    \u002F\u002F jQuery\n    $el.data('foo');\n\n    \u002F\u002F Native (use `getAttribute`)\n    el.getAttribute('data-foo');\n\n    \u002F\u002F Native (use `dataset` if only need to support IE 11+)\n    el.dataset['foo'];\n    ```\n\n- [1.12](#1.12) \u003Ca name='1.12'>\u003C\u002Fa> Selector containing string (case-sensitive)\n\n    ```js\n    \u002F\u002F jQuery\n    $(\"selector:contains('text')\");\n\n    \u002F\u002F Native\n    function contains(selector, text) {\n      var elements = document.querySelectorAll(selector);\n      return Array.from(elements).filter(function(element) {\n        return RegExp(text).test(element.textContent);\n      });\n    }\n    ```\n\n**[⬆ back to top](#table-of-contents)**\n\n## CSS & Style\n\n- [2.1](#2.1) \u003Ca name='2.1'>\u003C\u002Fa> CSS\n\n  + Get style\n\n    ```js\n    \u002F\u002F jQuery\n    $el.css('color');\n\n    \u002F\u002F Native\n    \u002F\u002F NOTE: Known bug, will return 'auto' if style value is 'auto'\n    const win = el.ownerDocument.defaultView;\n\n    \u002F\u002F null means not to return pseudo styles\n    win.getComputedStyle(el, null).color;\n    ```\n\n  + Set style\n\n    ```js\n    \u002F\u002F jQuery\n    $el.css({ color: '#f01' });\n\n    \u002F\u002F Native\n    el.style.color = '#f01';\n    ```\n\n  + Get\u002FSet Styles\n\n    ```js\n    \u002F\u002F jQuery\n    $el.css({ color: '#f01', 'border-color': '#f02' })\n    \n    \u002F\u002F Native\n    Object.assign(el.style, { color: '#f01', borderColor: '#f02' }) \n    ```\n\n  + Add class\n\n    ```js\n    \u002F\u002F jQuery\n    $el.addClass(className);\n\n    \u002F\u002F Native\n    el.classList.add(className);\n    ```\n\n  + Remove class\n\n    ```js\n    \u002F\u002F jQuery\n    $el.removeClass(className);\n\n    \u002F\u002F Native\n    el.classList.remove(className);\n    ```\n\n  + has class\n\n    ```js\n    \u002F\u002F jQuery\n    $el.hasClass(className);\n\n    \u002F\u002F Native\n    el.classList.contains(className);\n    ```\n\n  + Toggle class\n\n    ```js\n    \u002F\u002F jQuery\n    $el.toggleClass(className);\n\n    \u002F\u002F Native\n    el.classList.toggle(className);\n    ```\n\n- [2.2](#2.2) \u003Ca name='2.2'>\u003C\u002Fa> Width & Height\n\n  Width and Height are theoretically identical, take Height as example:\n\n  + Window height\n\n    ```js\n    \u002F\u002F window height\n    $(window).height();\n\n    \u002F\u002F without scrollbar, behaves like jQuery\n    window.document.documentElement.clientHeight;\n\n    \u002F\u002F with scrollbar\n    window.innerHeight;\n    ```\n\n  + Document height\n\n    ```js\n    \u002F\u002F jQuery\n    $(document).height();\n\n    \u002F\u002F Native\n    const body = document.body;\n    const html = document.documentElement;\n    const height = Math.max(\n      body.offsetHeight,\n      body.scrollHeight,\n      html.clientHeight,\n      html.offsetHeight,\n      html.scrollHeight\n    );\n    ```\n\n  + Element height\n\n    ```js\n    \u002F\u002F jQuery\n    $el.height();\n\n    \u002F\u002F Native\n    function getHeight(el) {\n      const styles = window.getComputedStyle(el);\n      const height = el.offsetHeight;\n      const borderTopWidth = parseFloat(styles.borderTopWidth);\n      const borderBottomWidth = parseFloat(styles.borderBottomWidth);\n      const paddingTop = parseFloat(styles.paddingTop);\n      const paddingBottom = parseFloat(styles.paddingBottom);\n      return height - borderBottomWidth - borderTopWidth - paddingTop - paddingBottom;\n    }\n\n    \u002F\u002F accurate to integer（when `border-box`, it's `height - border`; when `content-box`, it's `height + padding`）\n    el.clientHeight;\n\n    \u002F\u002F accurate to decimal（when `border-box`, it's `height`; when `content-box`, it's `height + padding + border`）\n    el.getBoundingClientRect().height;\n    ```\n\n- [2.3](#2.3) \u003Ca name='2.3'>\u003C\u002Fa> Position & Offset\n\n  + Position\n\n    Get the current coordinates of the element relative to the offset parent.\n\n    ```js\n    \u002F\u002F jQuery\n    $el.position();\n\n    \u002F\u002F Native\n    { left: el.offsetLeft, top: el.offsetTop }\n    ```\n\n  + Offset\n\n    Get the current coordinates of the element relative to the document.\n\n    ```js\n    \u002F\u002F jQuery\n    $el.offset();\n\n    \u002F\u002F Native\n    function getOffset (el) {\n      const box = el.getBoundingClientRect();\n\n      return {\n        top: box.top + window.pageYOffset - document.documentElement.clientTop,\n        left: box.left + window.pageXOffset - document.documentElement.clientLeft\n      };\n    }\n    ```\n\n- [2.4](#2.4) \u003Ca name='2.4'>\u003C\u002Fa> Scroll Top\n\n  Get the current vertical position of the scroll bar for the element.\n\n  ```js\n  \u002F\u002F jQuery\n  $(window).scrollTop();\n\n  \u002F\u002F Native\n  (document.documentElement && document.documentElement.scrollTop) || document.body.scrollTop;\n  ```\n\n**[⬆ back to top](#table-of-contents)**\n\n## DOM Manipulation\n\n- [3.1](#3.1) \u003Ca name='3.1'>\u003C\u002Fa> Remove\n\n  Remove the element from the DOM.\n\n  ```js\n  \u002F\u002F jQuery\n  $el.remove();\n\n  \u002F\u002F Native\n  el.parentNode.removeChild(el);\n  ```\n\n- [3.2](#3.2) \u003Ca name='3.2'>\u003C\u002Fa> Text\n\n  + Get text\n\n    Get the combined text contents of the element including their descendants,\n\n    ```js\n    \u002F\u002F jQuery\n    $el.text();\n\n    \u002F\u002F Native\n    el.textContent;\n    ```\n\n  + Set text\n\n    Set the content of the element to the specified text.\n\n    ```js\n    \u002F\u002F jQuery\n    $el.text(string);\n\n    \u002F\u002F Native\n    el.textContent = string;\n    ```\n\n- [3.3](#3.3) \u003Ca name='3.3'>\u003C\u002Fa> HTML\n\n  + Get HTML\n\n    ```js\n    \u002F\u002F jQuery\n    $el.html();\n\n    \u002F\u002F Native\n    el.innerHTML;\n    ```\n\n  + Set HTML\n\n    ```js\n    \u002F\u002F jQuery\n    $el.html(htmlString);\n\n    \u002F\u002F Native\n    el.innerHTML = htmlString;\n    ```\n\n- [3.4](#3.4) \u003Ca name='3.4'>\u003C\u002Fa> Append\n\n  Append child element after the last child of parent element\n\n  ```js\n  \u002F\u002F jQuery: unified syntax for DOMString and Node objects\n  $parent.append(newEl | '\u003Cdiv id=\"container\">Hello World\u003C\u002Fdiv>');\n\n  \u002F\u002F Native: different syntax\n  parent.insertAdjacentHTML('beforeend', '\u003Cdiv id=\"container\">Hello World\u003C\u002Fdiv>');\n  parent.appendChild(newEl);\n\n  \u002F\u002F Native (ES6-way): unified syntax\n  parent.append(newEl | '\u003Cdiv id=\"container\">Hello World\u003C\u002Fdiv>');\n  ```\n\n- [3.5](#3.5) \u003Ca name='3.5'>\u003C\u002Fa> Prepend\n\n  ```js\n  \u002F\u002F jQuery: unified syntax for DOMString and Node objects\n  $parent.prepend(newEl | '\u003Cdiv id=\"container\">Hello World\u003C\u002Fdiv>');\n\n  \u002F\u002F Native: different syntax\n  parent.insertAdjacentHTML('afterbegin', '\u003Cdiv id=\"container\">Hello World\u003C\u002Fdiv>');\n  parent.insertBefore(newEl, parent.firstChild);\n\n  \u002F\u002F Native (ES6-way): unified syntax\n  parent.prepend(newEl | '\u003Cdiv id=\"container\">Hello World\u003C\u002Fdiv>');\n  ```\n\n- [3.6](#3.6) \u003Ca name='3.6'>\u003C\u002Fa> insertBefore\n\n  Insert a new node before the selected elements\n\n  ```js\n  \u002F\u002F jQuery\n  $newEl.insertBefore(selector);\n\n  \u002F\u002F Native (HTML string)\n  el.insertAdjacentHTML('beforebegin ', '\u003Cdiv id=\"container\">Hello World\u003C\u002Fdiv>');\n\n  \u002F\u002F Native (Element)\n  const el = document.querySelector(selector);\n  if (el.parentNode) {\n    el.parentNode.insertBefore(newEl, el);\n  }\n  ```\n\n- [3.7](#3.7) \u003Ca name='3.7'>\u003C\u002Fa> insertAfter\n\n  Insert a new node after the selected elements\n\n  ```js\n  \u002F\u002F jQuery\n  $newEl.insertAfter(selector);\n\n  \u002F\u002F Native (HTML string)\n  el.insertAdjacentHTML('afterend', '\u003Cdiv id=\"container\">Hello World\u003C\u002Fdiv>');\n\n  \u002F\u002F Native (Element)\n  const el = document.querySelector(selector);\n  if (el.parentNode) {\n    el.parentNode.insertBefore(newEl, el.nextSibling);\n  }\n  ```\n\n- [3.8](#3.8) \u003Ca name='3.8'>\u003C\u002Fa> is\n\n  Return `true` if it matches the query selector\n\n  ```js\n  \u002F\u002F jQuery - Notice `is` also works with a function, an existing jQuery object or a DOM element, which are not of concern here\n  $el.is(selector);\n\n  \u002F\u002F Native\n  el.matches(selector);\n  ```\n- [3.9](#3.9) \u003Ca name='3.9'>\u003C\u002Fa> clone\n\n  Create a deep copy of an element: it copies the matched element as well as all of its descendant elements and text nodes.\n\n  ```js\n  \u002F\u002F jQuery. Sets parameter as `true` to indicate that event handlers should be copied along with the element.\n  $el.clone();\n\n  \u002F\u002F Native\n  el.cloneNode();\n\n  ```\n\n- [3.10](#3.10) \u003Ca name='3.10'>\u003C\u002Fa> empty\n\n  Remove all child nodes\n\n  ```js\n  \u002F\u002F jQuery\n  $el.empty();\n\n  \u002F\u002F Native\n  el.innerHTML = null;\n  ```\n\n- [3.11](#3.11) \u003Ca name='3.11'>\u003C\u002Fa> wrap\n\n  Wrap an HTML structure around each element\n\n  ```js\n  \u002F\u002F jQuery\n  $('.inner').wrap('\u003Cdiv class=\"wrapper\">\u003C\u002Fdiv>');\n\n  \u002F\u002F Native\n  Array.from(document.querySelectorAll('.inner')).forEach((el) => {\n    const wrapper = document.createElement('div');\n    wrapper.className = 'wrapper';\n    el.parentNode.insertBefore(wrapper, el);\n    wrapper.appendChild(el);\n  });\n  ```\n\n- [3.12](#3.12) \u003Ca name='3.12'>\u003C\u002Fa> unwrap\n\n  Remove the parents of the set of matched elements from the DOM\n\n  ```js\n  \u002F\u002F jQuery\n  $('.inner').unwrap();\n\n  \u002F\u002F Native\n  Array.from(document.querySelectorAll('.inner')).forEach((el) => {\n    let elParentNode = el.parentNode;\n\n    if(elParentNode !== document.body) {\n        elParentNode.parentNode.insertBefore(el, elParentNode);\n        elParentNode.parentNode.removeChild(elParentNode);\n    }\n  });\n  ```\n\n- [3.13](#3.13) \u003Ca name='3.13'>\u003C\u002Fa> replaceWith\n\n  Replace each element in the set of matched elements with the provided new content\n\n  ```js\n  \u002F\u002F jQuery\n  $('.inner').replaceWith('\u003Cdiv class=\"outer\">\u003C\u002Fdiv>');\n\n  \u002F\u002F Native (alternative) - latest, Edge17+\n  Array.from(document.querySelectorAll('.inner')).forEach((el) => {\n    const outer = document.createElement('div');\n    outer.className = 'outer';\n    el.replaceWith(outer);\n  });\n\n  \u002F\u002F Native\n  Array.from(document.querySelectorAll('.inner')).forEach((el) => {\n    const outer = document.createElement('div');\n    outer.className = 'outer';\n    el.parentNode.replaceChild(outer, el);\n  });\n  ```\n\n- [3.14](#3.14) \u003Ca name='3.14'>\u003C\u002Fa> simple parse\n\n  Parse a string into HTML\u002FSVG\u002FXML\n\n  ```js\n  \u002F\u002F jQuery\n  $(`\u003Col>\n    \u003Cli>a\u003C\u002Fli>\n    \u003Cli>b\u003C\u002Fli>\n  \u003C\u002Fol>\n  \u003Col>\n    \u003Cli>c\u003C\u002Fli>\n    \u003Cli>d\u003C\u002Fli>\n  \u003C\u002Fol>`);\n\n  \u002F\u002F Native\n  range = document.createRange();\n  parse = range.createContextualFragment.bind(range);\n\n  parse(`\u003Col>\n    \u003Cli>a\u003C\u002Fli>\n    \u003Cli>b\u003C\u002Fli>\n  \u003C\u002Fol>\n  \u003Col>\n    \u003Cli>c\u003C\u002Fli>\n    \u003Cli>d\u003C\u002Fli>\n  \u003C\u002Fol>`);\n  ```\n\n\n**[⬆ back to top](#table-of-contents)**\n\n## Ajax\n\n[Fetch API](https:\u002F\u002Ffetch.spec.whatwg.org\u002F) is the new standard to replace XMLHttpRequest to do ajax. It works on Chrome and Firefox, you can use polyfills to make it work on legacy browsers.\n\nTry [github\u002Ffetch](http:\u002F\u002Fgithub.com\u002Fgithub\u002Ffetch) on IE9+ or [fetch-ie8](https:\u002F\u002Fgithub.com\u002Fcamsong\u002Ffetch-ie8\u002F) on IE8+, [fetch-jsonp](https:\u002F\u002Fgithub.com\u002Fcamsong\u002Ffetch-jsonp) to make JSONP requests.\n\n- [4.1](#4.1) \u003Ca name='4.1'>\u003C\u002Fa> Load data from the server and place the returned HTML into the matched element.\n\n  ```js\n  \u002F\u002F jQuery\n  $(selector).load(url, completeCallback)\n\n  \u002F\u002F Native\n  fetch(url).then(data => data.text()).then(data => {\n    document.querySelector(selector).innerHTML = data\n  }).then(completeCallback)\n  ```\n\n**[⬆ back to top](#table-of-contents)**\n\n## Events\n\nFor a complete replacement with namespace and delegation, refer to https:\u002F\u002Fgithub.com\u002Foneuijs\u002Foui-dom-events\n\n- [5.0](#5.0) \u003Ca name='5.0'>\u003C\u002Fa> Document ready by `DOMContentLoaded`\n\n  ```js\n    \u002F\u002F jQuery\n    $(document).ready(eventHandler);\n\n    \u002F\u002F Native\n    \u002F\u002F Check if the DOMContentLoaded has already been completed\n    if (document.readyState !== 'loading') {\n      eventHandler();\n    } else {\n      document.addEventListener('DOMContentLoaded', eventHandler);\n    }\n\n    \u002F\u002F Native \n    \u002F\u002F Example 2 - Ternary Operator - Async\n    \u002F\u002F Check if the DOMContentLoaded has already been completed\n    (async function() {\n      (document.readyState !== 'loading') ?\n        eventHandler() : document.addEventListener('DOMContentLoaded',\n          function() {\n            eventHandler(); \u002F\u002F EventHandler\n          });\n    })();\n\n    \u002F\u002F Native\n    \u002F\u002F Example 3 - Ternary Operator - Non Async\n    \u002F\u002F Check if the DOMContentLoaded has already been completed\n    (function() {\n      (document.readyState !== 'loading') ?\n        eventHandler() : document.addEventListener('DOMContentLoaded',\n          function() {\n            eventHandler(); \u002F\u002F EventHandler\n          });\n    })();\n  ``` \n\n- [5.1](#5.1) \u003Ca name='5.1'>\u003C\u002Fa> Bind an event with on\n\n  ```js\n  \u002F\u002F jQuery\n  $el.on(eventName, eventHandler);\n\n  \u002F\u002F Native\n  el.addEventListener(eventName, eventHandler);\n  ```\n\n- [5.2](#5.2) \u003Ca name='5.2'>\u003C\u002Fa> Unbind an event with off\n\n  ```js\n  \u002F\u002F jQuery\n  $el.off(eventName, eventHandler);\n\n  \u002F\u002F Native\n  el.removeEventListener(eventName, eventHandler);\n  ```\n\n- [5.3](#5.3) \u003Ca name='5.3'>\u003C\u002Fa> Trigger\n\n  ```js\n  \u002F\u002F jQuery\n  $(el).trigger('custom-event', {key1: 'data'});\n\n  \u002F\u002F Native\n  if (window.CustomEvent) {\n    const event = new CustomEvent('custom-event', {detail: {key1: 'data'}});\n  } else {\n    const event = document.createEvent('CustomEvent');\n    event.initCustomEvent('custom-event', true, true, {key1: 'data'});\n  }\n\n  el.dispatchEvent(event);\n  ```\n\n**[⬆ back to top](#table-of-contents)**\n\n## Utilities\n\nMost of jQuery utilities are also found in the native API. Other advanced functions could be chosen from better utilities libraries, focusing on consistency and performance. [Lodash](https:\u002F\u002Flodash.com) is a recommended replacement.\n\n- [6.1](#6.1) \u003Ca name='6.1'>\u003C\u002Fa> Basic utilities\n\n  + isArray\n\n  Determine whether the argument is an array.\n\n  ```js\n  \u002F\u002F jQuery\n  $.isArray(array);\n\n  \u002F\u002F Native\n  Array.isArray(array);\n  ```\n\n  + isWindow\n\n  Determine whether the argument is a window.\n\n  ```js\n  \u002F\u002F jQuery\n  $.isWindow(obj);\n\n  \u002F\u002F Native\n  function isWindow(obj) {\n    return obj !== null && obj !== undefined && obj === obj.window;\n  }\n  ```\n\n  + inArray\n\n  Search for a specified value within an array and return its index (or -1 if not found).\n\n  ```js\n  \u002F\u002F jQuery\n  $.inArray(item, array);\n\n  \u002F\u002F Native\n  array.indexOf(item) > -1;\n\n  \u002F\u002F ES6-way\n  array.includes(item);\n  ```\n\n  + isNumeric\n\n  Determine if the argument passed is numerical.\n  Use `typeof` to decide the type or the `type` example for better accuracy.\n\n  ```js\n  \u002F\u002F jQuery\n  $.isNumeric(item);\n\n  \u002F\u002F Native\n  function isNumeric(n) {\n    return !isNaN(parseFloat(n)) && isFinite(n);\n  }\n  ```\n\n  + isFunction\n\n  Determine if the argument passed is a JavaScript function object.\n\n  ```js\n  \u002F\u002F jQuery\n  $.isFunction(item);\n\n  \u002F\u002F Native\n  function isFunction(item) {\n    if (typeof item === 'function') {\n      return true;\n    }\n    var type = Object.prototype.toString.call(item);\n    return type === '[object Function]' || type === '[object GeneratorFunction]';\n  }\n  ```\n\n  + isEmptyObject\n\n  Check to see if an object is empty (contains no enumerable properties).\n\n  ```js\n  \u002F\u002F jQuery\n  $.isEmptyObject(obj);\n\n  \u002F\u002F Native\n  function isEmptyObject(obj) {\n    return Object.keys(obj).length === 0;\n  }\n  ```\n\n  + isPlainObject\n\n  Check to see if an object is a plain object (created using “{}” or “new Object”).\n\n  ```js\n  \u002F\u002F jQuery\n  $.isPlainObject(obj);\n\n  \u002F\u002F Native\n  function isPlainObject(obj) {\n    if (typeof (obj) !== 'object' || obj.nodeType || obj !== null && obj !== undefined && obj === obj.window) {\n      return false;\n    }\n\n    if (obj.constructor &&\n        !Object.prototype.hasOwnProperty.call(obj.constructor.prototype, 'isPrototypeOf')) {\n      return false;\n    }\n\n    return true;\n  }\n  ```\n\n  + extend\n\n  Merge the contents of two or more objects together into a new object, without modifying either argument.\n  object.assign is part of ES6 API, and you could also use a [polyfill](https:\u002F\u002Fgithub.com\u002Fljharb\u002Fobject.assign).\n\n  ```js\n  \u002F\u002F jQuery\n  $.extend({}, object1, object2);\n\n  \u002F\u002F Native\n  Object.assign({}, object1, object2);\n  ```\n\n  + trim\n\n  Remove the white-space from the beginning and end of a string.\n\n  ```js\n  \u002F\u002F jQuery\n  $.trim(string);\n\n  \u002F\u002F Native\n  string.trim();\n  ```\n\n  + map\n\n  Translate all items in an array or object to new array of items.\n\n  ```js\n  \u002F\u002F jQuery\n  $.map(array, (value, index) => {\n  });\n\n  \u002F\u002F Native\n  array.map((value, index) => {\n  });\n  ```\n\n  + each\n\n  A generic iterator function, which can be used to seamlessly iterate over both objects and arrays.\n\n  ```js\n  \u002F\u002F jQuery\n  $.each(array, (index, value) => {\n  });\n\n  \u002F\u002F Native\n  array.forEach((value, index) => {\n  });\n  ```\n\n  + grep\n\n  Finds the elements of an array which satisfy a filter function.\n\n  ```js\n  \u002F\u002F jQuery\n  $.grep(array, (value, index) => {\n  });\n\n  \u002F\u002F Native\n  array.filter((value, index) => {\n  });\n  ```\n\n  + type\n\n  Determine the internal JavaScript [Class] of an object.\n\n  ```js\n  \u002F\u002F jQuery\n  $.type(obj);\n\n  \u002F\u002F Native\n  function type(item) {\n    const reTypeOf = \u002F(?:^\\[object\\s(.*?)\\]$)\u002F;\n    return Object.prototype.toString.call(item)\n      .replace(reTypeOf, '$1')\n      .toLowerCase();\n  }\n  ```\n\n  + merge\n\n  Merge the contents of two arrays together into the first array.\n\n  ```js\n  \u002F\u002F jQuery, doesn't remove duplicate items\n  $.merge(array1, array2);\n\n  \u002F\u002F Native, doesn't remove duplicate items\n  function merge(...args) {\n    return [].concat(...args)\n  }\n\n  \u002F\u002F ES6-way, doesn't remove duplicate items\n  array1 = [...array1, ...array2]\n\n  \u002F\u002F Set version, does remove duplicate items\n  function merge(...args) {\n    return Array.from(new Set([].concat(...args)))\n  }\n  ```\n\n  + now\n\n  Return a number representing the current time.\n\n  ```js\n  \u002F\u002F jQuery\n  $.now();\n\n  \u002F\u002F Native\n  Date.now();\n  ```\n\n  + proxy\n\n  Takes a function and returns a new one that will always have a particular context.\n\n  ```js\n  \u002F\u002F jQuery\n  $.proxy(fn, context);\n\n  \u002F\u002F Native\n  fn.bind(context);\n  ```\n\n  \u003Ca name=\"makeArray\">\u003C\u002Fa>+ makeArray\n\n  Convert an array-like object into a true JavaScript array.\n\n  ```js\n  \u002F\u002F jQuery\n  $.makeArray(arrayLike);\n\n  \u002F\u002F Native\n  Array.prototype.slice.call(arrayLike);\n\n  \u002F\u002F ES6-way: Array.from() method\n  Array.from(arrayLike);\n\n  \u002F\u002F ES6-way: spread operator\n  [...arrayLike];\n  ```\n\n- [6.2](#6.2) \u003Ca name='6.2'>\u003C\u002Fa> Contains\n\n  Check to see if a DOM element is a descendant of another DOM element.\n\n  ```js\n  \u002F\u002F jQuery\n  $.contains(el, child);\n\n  \u002F\u002F Native\n  el !== child && el.contains(child);\n  ```\n\n- [6.3](#6.3) \u003Ca name='6.3'>\u003C\u002Fa> Globaleval\n\n  Execute some JavaScript code globally.\n\n  ```js\n  \u002F\u002F jQuery\n  $.globaleval(code);\n\n  \u002F\u002F Native\n  function Globaleval(code) {\n    const script = document.createElement('script');\n    script.text = code;\n\n    document.head.appendChild(script).parentNode.removeChild(script);\n  }\n\n  \u002F\u002F Use eval, but context of eval is current, context of $.Globaleval is global.\n  eval(code);\n  ```\n\n- [6.4](#6.4) \u003Ca name='6.4'>\u003C\u002Fa> parse\n\n  + parseHTML\n\n  Parses a string into an array of DOM nodes.\n\n  ```js\n  \u002F\u002F jQuery\n  $.parseHTML(htmlString);\n\n  \u002F\u002F Native\n  function parseHTML(string) {\n    const context = document.implementation.createHTMLDocument();\n\n    \u002F\u002F Set the base href for the created document so any parsed elements with URLs\n    \u002F\u002F are based on the document's URL\n    const base = context.createElement('base');\n    base.href = document.location.href;\n    context.head.appendChild(base);\n\n    context.body.innerHTML = string;\n    return context.body.children;\n  }\n  ```\n- [6.5](#6.4) \u003Ca name='6.5'>\u003C\u002Fa> exists\n\n+ exists\n\n  Check if an element exists in the DOM\n\n  ```js\n  \u002F\u002F jQuery\n  if ($('selector').length) {\n     \u002F\u002F exists\n  }\n\n  \u002F\u002F Native\n  var element =  document.getElementById('elementId');\n  if (typeof(element) != 'undefined' && element != null)\n  {\n     \u002F\u002F exists\n  }\n  ```\n\n**[⬆ back to top](#table-of-contents)**\n\n## Promises\n\nA promise represents the eventual result of an asynchronous operation. jQuery has its own way to handle promises. Native JavaScript implements a thin and minimal API to handle promises according to the [Promises\u002FA+](http:\u002F\u002Fpromises-aplus.github.io\u002Fpromises-spec\u002F) specification.\n\n- [7.1](#7.1) \u003Ca name='7.1'>\u003C\u002Fa> done, fail, always\n\n  `done` is called when promise is resolved, `fail` is called when promise is rejected, `always` is called when promise is either resolved or rejected.\n\n  ```js\n  \u002F\u002F jQuery\n  $promise.done(doneCallback).fail(failCallback).always(alwaysCallback)\n\n  \u002F\u002F Native\n  promise.then(doneCallback, failCallback).then(alwaysCallback, alwaysCallback)\n  ```\n\n- [7.2](#7.2) \u003Ca name='7.2'>\u003C\u002Fa> when\n\n  `when` is used to handle multiple promises. It will resolve when all promises are resolved, and reject if either one is rejected.\n\n  ```js\n  \u002F\u002F jQuery\n  $.when($promise1, $promise2).done((promise1Result, promise2Result) => {\n  });\n\n  \u002F\u002F Native\n  Promise.all([$promise1, $promise2]).then([promise1Result, promise2Result] => {});\n  ```\n\n- [7.3](#7.3) \u003Ca name='7.3'>\u003C\u002Fa> Deferred\n\n  Deferred is a way to create promises.\n\n  ```js\n  \u002F\u002F jQuery\n  function asyncFunc() {\n    const defer = new $.Deferred();\n    setTimeout(() => {\n      if(true) {\n        defer.resolve('some_value_computed_asynchronously');\n      } else {\n        defer.reject('failed');\n      }\n    }, 1000);\n\n    return defer.promise();\n  }\n\n  \u002F\u002F Native\n  function asyncFunc() {\n    return new Promise((resolve, reject) => {\n      setTimeout(() => {\n        if (true) {\n          resolve('some_value_computed_asynchronously');\n        } else {\n          reject('failed');\n        }\n      }, 1000);\n    });\n  }\n\n  \u002F\u002F Deferred way\n  function defer() {\n    const deferred = {};\n    const promise = new Promise((resolve, reject) => {\n      deferred.resolve = resolve;\n      deferred.reject = reject;\n    });\n\n    deferred.promise = () => {\n      return promise;\n    };\n\n    return deferred;\n  }\n\n  function asyncFunc() {\n    const defer = defer();\n    setTimeout(() => {\n      if(true) {\n        defer.resolve('some_value_computed_asynchronously');\n      } else {\n        defer.reject('failed');\n      }\n    }, 1000);\n\n    return defer.promise();\n  }\n  ```\n\n**[⬆ back to top](#table-of-contents)**\n\n## Animation\n\n- [8.1](#8.1) \u003Ca name='8.1'>\u003C\u002Fa> Show & Hide\n\n  ```js\n  \u002F\u002F jQuery\n  $el.show();\n  $el.hide();\n\n  \u002F\u002F Native\n  \u002F\u002F More detail about show method, please refer to https:\u002F\u002Fgithub.com\u002Foneuijs\u002Foui-dom-utils\u002Fblob\u002Fmaster\u002Fsrc\u002Findex.js#L363\n  el.style.display = ''|'inline'|'inline-block'|'inline-table'|'block';\n  el.style.display = 'none';\n  ```\n\n- [8.2](#8.2) \u003Ca name='8.2'>\u003C\u002Fa> Toggle\n\n  Display or hide the element.\n\n  ```js\n  \u002F\u002F jQuery\n  $el.toggle();\n\n  \u002F\u002F Native\n  if (el.ownerDocument.defaultView.getComputedStyle(el, null).display === 'none') {\n    el.style.display = ''|'inline'|'inline-block'|'inline-table'|'block';\n  } else {\n    el.style.display = 'none';\n  }\n  ```\n\n- [8.3](#8.3) \u003Ca name='8.3'>\u003C\u002Fa> FadeIn & FadeOut\n\n  ```js\n  \u002F\u002F jQuery\n  $el.fadeIn(3000);\n  $el.fadeOut(3000);\n\n  \u002F\u002F Native fadeOut\n  function fadeOut(el, ms) {\n    if (ms) {\n      el.style.transition = `opacity ${ms} ms`;\n      el.addEventListener(\n        'transitionend',\n        function(event) {\n          el.style.display = 'none';\n        },\n        false\n      );\n    }\n    el.style.opacity = '0';\n  }\n\n  \u002F\u002F Native fadeIn\n  function fadeIn(elem, ms) {\n    elem.style.opacity = 0;\n\n    if (ms) {\n      let opacity = 0;\n      const timer = setInterval(function() {\n        opacity += 50 \u002F ms;\n        if (opacity >= 1) {\n          clearInterval(timer);\n          opacity = 1;\n        }\n        elem.style.opacity = opacity;\n      }, 50);\n    } else {\n      elem.style.opacity = 1;\n    }\n  }\n  ```\n\n- [8.4](#8.4) \u003Ca name='8.4'>\u003C\u002Fa> FadeTo\n\n  Adjust the opacity of the element.\n\n  ```js\n  \u002F\u002F jQuery\n  $el.fadeTo('slow',0.15);\n  \u002F\u002F Native\n  el.style.transition = 'opacity 3s'; \u002F\u002F assume 'slow' equals 3 seconds\n  el.style.opacity = '0.15';\n  ```\n\n- [8.5](#8.5) \u003Ca name='8.5'>\u003C\u002Fa> FadeToggle\n\n  Display or hide the element by animating their opacity.\n\n  ```js\n  \u002F\u002F jQuery\n  $el.fadeToggle();\n\n  \u002F\u002F Native\n  el.style.transition = 'opacity 3s';\n  const { opacity } = el.ownerDocument.defaultView.getComputedStyle(el, null);\n  if (opacity === '1') {\n    el.style.opacity = '0';\n  } else {\n    el.style.opacity = '1';\n  }\n  ```\n\n- [8.6](#8.6) \u003Ca name='8.6'>\u003C\u002Fa> SlideUp & SlideDown\n\n  ```js\n  \u002F\u002F jQuery\n  $el.slideUp();\n  $el.slideDown();\n\n  \u002F\u002F Native\n  const originHeight = '100px';\n  el.style.transition = 'height 3s';\n  \u002F\u002F slideUp\n  el.style.height = '0px';\n  \u002F\u002F slideDown\n  el.style.height = originHeight;\n  ```\n\n- [8.7](#8.7) \u003Ca name='8.7'>\u003C\u002Fa> SlideToggle\n\n  Display or hide the element with a sliding motion.\n\n  ```js\n  \u002F\u002F jQuery\n  $el.slideToggle();\n\n  \u002F\u002F Native\n  const originHeight = '100px';\n  el.style.transition = 'height 3s';\n  const { height } = el.ownerDocument.defaultView.getComputedStyle(el, null);\n  if (parseInt(height, 10) === 0) {\n    el.style.height = originHeight;\n  } else {\n   el.style.height = '0px';\n  }\n  ```\n\n- [8.8](#8.8) \u003Ca name='8.8'>\u003C\u002Fa> Animate\n\n  Perform a custom animation of a set of CSS properties.\n\n  ```js\n  \u002F\u002F jQuery\n  $el.animate({ params }, speed);\n\n  \u002F\u002F Native\n  el.style.transition = 'all ' + speed;\n  Object.keys(params).forEach((key) => {\n    el.style[key] = params[key];\n  });\n  ```\n\n## Alternatives\n\n* [You Might Not Need jQuery](http:\u002F\u002Fyoumightnotneedjquery.com\u002F) - Examples of how to do common event, element, ajax etc with plain javascript.\n* [npm-dom](http:\u002F\u002Fgithub.com\u002Fnpm-dom) and [webmodules](http:\u002F\u002Fgithub.com\u002Fwebmodules) - Organizations you can find individual DOM modules on NPM\n\n## Browser Support\n\n![Chrome][chrome-image] | ![Firefox][firefox-image] | ![IE][ie-image] | ![Opera][opera-image] | ![Safari][safari-image]\n--- | --- | --- | --- | --- |\nLatest ✔ | Latest ✔ | 10+ ✔ | Latest ✔ | 6.1+ ✔ |\n\n# License\n\nMIT\n\n[chrome-image]: https:\u002F\u002Fraw.github.com\u002Falrra\u002Fbrowser-logos\u002Fmaster\u002Fsrc\u002Fchrome\u002Fchrome_48x48.png\n[firefox-image]: https:\u002F\u002Fraw.github.com\u002Falrra\u002Fbrowser-logos\u002Fmaster\u002Fsrc\u002Ffirefox\u002Ffirefox_48x48.png\n[ie-image]: https:\u002F\u002Fraw.github.com\u002Falrra\u002Fbrowser-logos\u002Fmaster\u002Fsrc\u002Farchive\u002Finternet-explorer_9-11\u002Finternet-explorer_9-11_48x48.png\n[opera-image]: https:\u002F\u002Fraw.github.com\u002Falrra\u002Fbrowser-logos\u002Fmaster\u002Fsrc\u002Fopera\u002Fopera_48x48.png\n[safari-image]: https:\u002F\u002Fraw.github.com\u002Falrra\u002Fbrowser-logos\u002Fmaster\u002Fsrc\u002Fsafari\u002Fsafari_48x48.png\n","该项目展示了如何使用原生JavaScript实现jQuery中常见的查询、样式、DOM操作、Ajax和事件处理等功能。它总结了现代浏览器已支持的DOM\u002FBOM API，提供了一种不依赖jQuery进行前端开发的方式。项目涵盖了选择器、CSS样式、DOM操作、Ajax请求、事件监听等核心功能，并且支持IE 10+浏览器。适合于希望减少对第三方库依赖或在现代前端框架（如React, Angular, Vue）中直接操作DOM的开发者参考。需要注意的是，虽然提供了jQuery方法的替代方案，但在某些场景下可能并不完全等效，建议使用前进行充分测试。",2,"2026-06-11 02:52:46","top_language"]