Зачем использовать getElementById, если можно получить элемент через переменную с именем, равным значению атрибута id?

150
15 ноября 2018, 21:50

Собственно век живи век учись!

window.onload = function() { 
  div_1.onclick = function() { 
    div_2.value = div_1.innerHTML; 
  } 
}
<div id="div_1">TEXT</div> 
<input type="text" id="div_2" value="" />

Работает во всех браузерах которые есть только на компе!

Вопрос: Зачем объявлять переменную типа как

var mydiv = document.getElementById("mydiv");

и потом к ней обращаться, если обращение можно сделать сразу к mydiv? Поясните!

UPD: @ling жду Ваш персональный визит! Ваши знания были испытаны собственным js кодом не раз)

Answer 1

Для начала - немного теории. Эту ИМХО глупость, в свое время, начал IE, остальными браузерами это не поддерживалось, после - это стало поддерживаться хромом, в настоящее же время - такого рода поведение утвержденно html5 стандартом (да, и там кое-что через Ж, ну да не суть). Соответственно по поводу поддержки - это поддержка действительно на уровне.(за исключением того парадокса, что это не будет работать в старых не IE), более того - поддержка останеться и никуда она не денется, соответственно я не совсем понимаю - что правильного в ответе @Alex Silaev ?

Ну а теперь перейдем к практической части, такого рода элементы хранятся в глобальной области видимости, соответственно, например, может возникнуть ситуация, типа:

<!-- наш HTML -->
<div id="hello">классно работает!11!</div>
<!-- один из наших скриптов -->
var hello = function(){ /* function code... */ }
<!-- другой наш скрипт -->
hello.onclick = function(){ alert(this.innerHTML); }

Что в таком случае произойдет я думаю понятно. Естественно кто-то может возразить, мол - если делать все акуратно, то все будет ок и я не отрицаю, нередко так все и будет. Но, мягко говоря - не всегда. Чем больше кода у вас будет - тем выше будет становиться вероятность поймать неприятный баг. Конечно если вы понимаете что глобальные переменные зло и т.д. и т.п. - вы будете грамотно структуировать свой код, но, в таком случае и элементы выбирать, тоже, будете по человечески. В противном случае - у вас идет жесткая привязка к структуре html, еще жоще чем при document.getElementById('someId'). На самом деле - все это выглядит как магия, соответственно просматривая код, банально, не понятно - откуда взялся, например, этот hello, особенно очевидным это становиться тогда, когда объемы кода становятся, хотя-бы 300+ строк. Допустим мне нужно изменить этот id, я меняю его в DOM'e, ищу по скриптам где он используется, но я так и не нахожу т.к. (уж будьте уверены) - искать я буду именно $ в случае jq, prototype и getElementById в случае "pure" JS, сейчас я пишу не в контексте себя лично, а в контексте человека который будет смотреть написанный вами код, вашего напарника или того, кто заменяет вас на работе. И, на самом деле - это нормально, знают это далеко не все и, даже в книгах, где об этом упомянаеться - кратко пишут мол, смотрите вот так вот можно делать, немного описывают как это работает и потом - можно, но не нужно и во всех книгах дальше пишется что-то типа - соответственно в нашей книге мы так делать не будем. Конечно я понимаю, что далеко не всегда в книгах все пишут правильно (особенно это справедливо с книгами по javascript'у), но то, что об этом написано далеко не во всех книгах и то, что, например, вы - до сиих пор не знали этого, по моему, уже говорит о том что никому это не нужно. оффтоп - и подтверждает поговорку "меньше знаешь - лучше спишь" =)

Еще хотел бы добавить, к описаному выше, неудобство в плане парной работы с верстальщиком или, что, в данном случае, намного хуже - с другим JS разработчиком.

Вообщем кратко резюмируя - так делать, в абсолютном большинстве случаев, мягко говоря - не рекомендую (не только я), причины (не выдумывая чего-то сложного, а, в реальной жизни, поверьте мне - будут проблемы поинтереснее) описаны выше. Что мы выигрываем? Да, собственно, практически ничего мы и не выигрываем...

Еще одним "типа" аргументом может быть то, что это быстрее - возможно это и так, но getElementById работает настолько быстро (причем абсолютно везде), что руководствоваться этим - не серьезно. Но даже, если вы хотите, то сделайте хотя-бы как-то так:

function getElementById(id) {
    return window[id] !== undefined && window[id].id === id
                                 ? window[id] : document.getElementById(id);
}

Собственно подобный подход решает проблему "стирания", но, в то-же время, невилизирует краткость записи. С другой стороны - эта функция будет нормально работать везде и в DOM, если элемент сохранился в window - не полезет. Еще раз акцентирую ваше внимание - это экономия на спичках.

Парирую кусок UPD by @Антон Мухин по поводу id вида "div-id" - их легко и просто можно достать вызовом window["div-id"], ничего браузер не вычисляет.

Постараюсь подвести очень краткие итоги - просто не используйте это, знайте для того, что-бы можно было понять как работает тот или иной javascript код, не более (ИМХО)

PS: 2 @northerner никто не говорит что они там дураки, они хотят сделать как лучше. По поводу javascript без getElementById - если в вопросе явно спрашивается, "как лучше getElementById или так?", какое отношение к вопросу имеет то, о чем писали вы? Либо я чего-то недопонимаю, либо вы не внимательно читали вопрос.

UPD: Время уже все показало, если бы это было-бы нужно это бы уже давно использовалось бы в широких кругах, т.к. ничего подобного не наблюдается - это никому не нужно (вернее кому-то нужно раз принимают такие стандарты, но вот кому - я без понятия). Еще раз подчерну - речь именно о браузерном javascript'е, возможно, где-то, это удобно и практикуется большинством, тогда конечно - юзайте на здоровье (спасибо кэп).

Answer 2

Обсуждение на StackOverflow и еще.

Это поведение IE, которое было потом скопировано другими браузерами, и упомянуто в стандарте HTML5. см. 5.2.4 Named access on the Window object.

Суть заключается в том, что в данном случае обращение идет к свойству объекта window. Другими словами, браузеры делают возможным доступ к элементам с указанным id через объект window, который является глобальным контекстом, поэтому window['id'] можно и не писать, достаточно id, ну за исключением невалидных id с точки зрения имени переменной (да, минусы и проч.)...

Такая практика никому особо не нравится и идет речь, чтобы если не убрать данное поведение из стандарта, то сделать доступным хотя бы только для quirks mode, а standard mode не трогать.

Consider making the global scope pollution by names/ids quirks-only

Answer 3

Ответ просто в правильности подхода. Никто не гарантирует, что такой метод "проживет" или будет поддерживаться и дальше. А getElementById будет.

Это примерно тоже самое, что и дорогу на красный свет переходить. Ведь можно, но никто не гарантирует, что после этого с вами ничего не произойдет. (Хотя в России может произойти и на зеленый). Но суть не в этом, а в том, что подходы разные и вероятность несчастного случая тоже. Тем более, если вдруг не будет поддержки этой штуки, то вам приедтся весь код просматривать и все менять. А если не будет поддержки getElementById, то я просто ее переобъявлю и она у меня появится :)

И собственно ответ на вопрос - скорее отстанете от жизни, если будете его использовать :)

Answer 4

А вы попробуйте дать элементу

<div id="div-1">TEXT</div>

Как думаете, что будет пытаться сделать браузер при выполнении div-1?
Правильно! Он будет пытаться от переменной div вычесть 1! Как в таком случае обойтись без выражения

var mydiv = document.getElementById("div-1");

???
UPD1
Еще можно добавить! Бывают элементы, создаваемые во время выполнения. Ну им, стало быть, ID даются динамически. Было бы глупо для таких случаев не динамически ставить переменные вот так:

my_dynamic_id.onclick = function() {
    //Бла-бла-бла
}

Лучше, же, наверное, так:

// начало какого-нибудь цикла обработки
//....
//получаем ID из какой-нить функции, предоставляющей id элементов
var my_id_i = document.getElementById(getNextDynamicId());
my_id_i.onclick = function() {
    //Бла-бла-бла
}

Тут как получается такая ситуация когда можно обращаться непосредственно к элементу my_div напрямую? Просто при создании этого DIV-элемента, появляется и глобальная переменная my_div. Но она перезапишется, объяви вы глобально переменную с таким же именем, как ID элемента:

<script type="text/javascript">
    var my_div = 'АГА!!!!';
    function aga() {
        alert(my_div);
        alert(document.getElementById(my_div));    
    }
</script>

Тут, в первом случае, выведется "АГА!!!!", во втором что-то вроде "HTMLDivElement".
Вот и получается, что ваше приложение может по ошибке или недосмотру сломаться из-за нечаянного объявления переменной с таким же именем, как ID, как у вашего элемента.
Так что же вышло? Браузер сначала объявил глобальную переменную my_div, которую мы успешно переписали!
Ну вот как-то так. Даже мой, приведенный тут случай, можно считать "подводным камнем".

Answer 5

Отвечу в ответ на свой вопрос в споре ответов и комментариев отозвавшихся...

Суть: Я всегда использую нативный js в рамках своих проетов, которыми занимаюсь только я.

@Alex Silaev пожалуй ваш ответ пока лучший но учитывая часть вашего ответа:

если не будет поддержки getElementById, то я просто ее переобъявлю и она у меня появится

я напишу некий умный php скрипт котрый преобразует все нужные вхождения в нужных местах и отформатирует js скрипт под все мега новшества дабы не ковыряться в километровом js коде! На данный момент я не вижу причин не использовать тот метод который я привел в примере! Снова ословлюсь в рамках своего проекта!

@Антон Мухин открою вам интересную функцию:

function $(id) { return document.getElementById(id); }

и далее можите использовать строку из моего примера в вопросе как

$("div_1").onclick = function() //...

Теперь скажу что в рамках своего проекта я чотко знаю что нужно использовать нижнее подчеркивание а не дефис, это вопервых.

Во вторых я такую мишуру редко использую и в основном в css клсасах! Что относится к программному коду и названиях ID происходит следующим образом var nodeName или id="idName" давно стараюсь исключать мишуру и лишние знаки!

READ ALSO
Виртуальный метод при композиции

Виртуальный метод при композиции

Объект класса с двумя методами getOuter и getInner оборачивается другим классом, имеющим такой же интерфейс, но используется не наследование а композиция,...

159
Передать данные по нажатию кнопки

Передать данные по нажатию кнопки

Возник интересный вопрос, как мне лучше всего передавать someValue в somefunction, при нажатии кнопки: оформить все это в форму или лучше использовать...

148
Slick slider с ползунком

Slick slider с ползунком

Подскажите решение как реализовать синхронизацию ползунка с картинкамиОчевидно, но на всякий случай: Крутим ползунок вправо - слайды двигаются...

150
Работа с скролом у блока

Работа с скролом у блока

Возникло несколько моментов с прокруткой блокаПрошу заметить, тут меня не интересует прокрутка страницы, как оказалось

142