JavaScript должен быть написан на компьютере. Само собой разумеется. Но в 2011 году во время моего последнего выпускного экзамена мне пришлось вручную писать функции JavaScript.
Да, мне физически приходилось писать циклы, переменные, селекторы и даже:
document.getElementById();
И я ненавидел писать это. Это заняло так много места на моей бумаге. Я даже не шучу. Иди напиши это. Функции JavaScript никогда не следует писать на бумаге.
Вместо этого я сделал что-то вроде этого:
function getId(id) { return document.getElementById(id); }
И если мне это было нужно, я просто звонил getId()
. Еще я сделал его для getClass()
, потому что я ботаник.
Год спустя я изучил jQuery, и теперь моя функция getId()
стала:
jQuery('#id');
Тот факт, что я мог также использовать селекторы CSS, поразил меня. Я мог бы сделать вот что:
jQuery('.list:first-child ~ li[icon*="fa-"]');
и это сработало! jQuery открывает столько возможностей!
Но это было в 2011 году. Теперь наступил 2021 год. Люди по-прежнему постоянно используют jQuery, но сейчас это похоже на темное черное искусство. А, jQuery? Да, просто сделай это ... Но почему бы вместо этого не использовать Vanilla.js ™ ? Он работает намного лучше.
И это честно. Благодаря таким вещам, как document.querySelector()
и document.querySelectorAll()
, теперь мы можем использовать селекторы CSS в обычном JavaScript. Вы даже можете использовать document.querySelector()
для замены document.getElementById()
, если хотите. Разница в том, что первая работает со скоростью 15 миллионов звонков в секунду, а вторая - со скоростью 7 миллионов звонков в секунду.
Которые, конечно, оба очень быстрые.
Но что, если бы был более быстрый способ? Тот, в котором не было document.getElementById()
? Тот, который, если бы мой учитель выполнял свою работу в высшем учебном заведении, мне даже не нужно было бы делать getId()
?
Что ж, есть.
Пожалуйста, примите во внимание следующее:
<div id="myElement"><div> <script> console.log(myElement); </script>
Когда вы создаете элемент HTML с использованием идентификатора, уже создается глобальное пространство имен. Нет никакой причины использовать document.getElementById()
. Я знаю, это супер круто. Но есть несколько минусов.
Во-первых, это «плохая практика». Это пережиток времен Browser Wars, и хотя он все еще поддерживается сегодня, его не рекомендуется использовать. В нескольких документах, которые я прочитал, говорится, что это также может привести к «хрупкому» коду, что имеет «хрупкий» смысл (ха), потому что если вы добавите эту строку:
var myElement = 'whatever';
Вы теряете доступ к своей глобальной переменной. Но то же самое буквально для всего с JavaScript. Если вы сделаете это:
var overwritable = 'whatever'; var overwritable = 'whatever yourself'; console.log(overwritable);
Он регистрирует whatever yourself
. Так что это не более хрупко, чем уже есть JavaScript.
Также существует проблема, что некоторые люди являются монстрами и используют дефисы вместо camelCase (или, idk, подчеркивания?) При идентификации своих элементов. В имени переменной JavaScript не может быть дефиса, поэтому это будет сломано.
Но мы сейчас рассмотрим этот вопрос.
Если вы действительно проверите скорость между этими двумя:
<div id="myElement"></div> <div id="myElement2"></div> <script> var a = performance.now(); console.log(myElement); var b = performance.now(); var c = performance.now(); console.log(document.getElementById('myElement2')); var d = performance.now(); console.log("Global call took " + (b - a) + " milliseconds."); console.log("By Id call took " + (d - c) + " milliseconds."); </script>
Вы увидите, что document.getElementById()
работает примерно в 2 раза быстрее. Итак, глобальная переменная не быстрее.
Но…
Причина этого в том, что доступ к глобальным переменным выполняется медленно. Ему необходимо проанализировать объект window
, найти значение и затем вернуть его. Так что, если мы не сделаем его глобальным? Что, если мы сделаем это местным?
const fasterMyPrecious
= myElement;
И мы выбрали const
, потому что не хотим «ломкого кода» или чего-то еще, чтобы его нельзя было перезаписать. Это также решило проблему с дефисом, поскольку мы должны назвать нашу локальную переменную.
Итак, как это работает сейчас? Что ж, он варьируется между каждым вызовом на ± 0,01 миллисекунды каждый раз, когда запускается скрипт, поэтому, если мы поместим его в цикл и запустим его 1000 раз, мы получим:
Global call took 88.68000004440546 milliseconds. By Id call took 92.66000072238967 milliseconds.
"Но это несправедливо!" Вы кричите. «fasterMyPrecious
кэшируется, а document.getElementById()
- нет».
«Хорошо», - отвечаю я. "Тогда давайте закэшируем их обоих".
Наш текущий рабочий сценарий выглядит следующим образом:
<div id="myElement"></div> <div id="myElement2"></div> <script> constfasterMyPrecious
= myElement; const cachedById = document.getElementById('myElement2'); var a, b, c, d; a = b = c = d = 0; console.log('start'); for (var i = 0; i < 1000; i++) { a += performance.now(); console.log(fasterMyPrecious
); b += performance.now(); c += performance.now(); console.log(cachedById); d += performance.now(); } console.log("Global call took " + (b - a) + " milliseconds."); console.log("By Id call took " + (d - c) + " milliseconds."); </script>
Результат:
Global call took 88.55000001494773 milliseconds. By Id call took 91.63999947486445 milliseconds.
Но вот крестраж в целом. Если мы перевернем скрипт и поместим cachedById
выше fasterMyPrecious
:
<div id="myElement"></div> <div id="myElement2"></div> <script> constfasterMyPrecious
= myElement; const cachedById = document.getElementById('myElement2'); var a, b, c, d; a = b = c = d = 0; console.log('start'); for (var i = 0; i < 1000; i++) { //now above c += performance.now(); console.log(cachedById); d += performance.now(); //now below a += performance.now(); console.log(fasterMyPrecious
); b += performance.now(); } console.log("Global call took " + (b - a) + " milliseconds."); console.log("By Id call took " + (d - c) + " milliseconds."); </script>
Они распечатывают cachedById
(он же document.getElementById
) быстрее.
Global call took 92.1750005800277 milliseconds. By Id call took 89.70999921439216 milliseconds.
Хорошо, хорошо, хорошо. Но что, если мы запустим их независимо друг от друга? Тогда получаем следующее:
By Id call took 93.04500030702911 milliseconds. Global call took 86.50500001385808 milliseconds.
С fasterByPrecious
(он же глобальный селектор пространства имен) на 6,54000029317 миллисекунд быстрее.
Конечно, это незначительное различие можно объяснить буквально чем угодно. Даже сетевой пинг может сбить это с толку. Итак, я сделал немыслимое, отключил свой Интернет (так как вам не нужен Интернет для запуска JavaScript) и снова запустил его:
By Id call took 98.13499977462925 milliseconds. Global call took 94.89000029861927 milliseconds.
И fasterMyPrecious
снова чемпион.
Таким образом, хотя может быть более быстрое решение, чем document.getElementById()
, я действительно не уверен, что вы будете делать со всем этим свободным временем.