24

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

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 кодом не раз)

Air
  • 14,505
Palmervan
  • 9,350
  • О_о думаю камни подводные тут есть – Олег Архипов Mar 19 '12 at 15:02
  • Т.е. по Вашему 4 строчки короче, чем одна? Или я не понял? – butteff Mar 19 '12 at 15:02
  • 1
    @butteff, он про обращение:
    div_2.value
    
    – Олег Архипов Mar 19 '12 at 15:03
  • 5
    Собственно жду гуру) – Palmervan Mar 19 '12 at 15:04
  • Поддерживаю ответ Alex'а. Еще может быть, чтобы переменные не мешать. Объявили вы допустим где-нибудь переменную window.mydiv как string. А потом захотели обратиться к Dom'у с таким же ID, а вам js дулю (ну или еще че) покажет)) А вообще Вам @Palmervan большое спасибо) Только щас узнал, что так можно делать) – Dobby007 Mar 19 '12 at 15:30
  • @Dobby007 та я сам был вшоке) – Palmervan Mar 19 '12 at 15:48
  • @Alex Silaev возражений не имею, все принято к сведению! Ответ принят! – Palmervan Mar 19 '12 at 18:39
  • 1
    @Palmervan, Вы почаще отставайте от жизни =) С рождения ничего подобного не знал и даже в голову не приходило) + к вопросу)) – Виталий Кустов Mar 19 '12 at 18:50
  • 3
    Я недавно вот что для себя открыл
    var obj = {};
    var n = function() { return false; }
    var obj2 = { a: 15 }
    obj[n] = 3;
    obj[obj2] = 5;
    
    

    По-моему, это страшно))

    – Sh4dow Mar 19 '12 at 19:02
  • Ага, действительно страшно!!!
    Думаю, читать такое в чужом коде - ...... просто нет слов)
    – Anton Mukhin Mar 19 '12 at 19:17
  • Проверил. При добавлении doctype'а код не работает в FF. Плюс, как уже было сказано, не факт, что этот стиль кода сохранится в следующих версиях браузеров. – ling Mar 20 '12 at 07:01
  • 1
    @ling вам бы тоже почитать мой ответ по этому поводу –  Mar 20 '12 at 07:19
  • Почитал, плюсанул. Почитал также и Yura Ivanov. Такое ощущение, что рано или поздно либо сделают полновесную поддержку такого именования, либо его выпилят из стандартов. Мне лично это не нравится, как раз по причине захламления кода. – ling Mar 20 '12 at 07:49
  • @Sh4dow, ну, я думаю, открытие в универсальности названия свойства (в смысле переменная какого типа будет в его названии). В первом случае свойство назвалось логической переменной false, то есть можно было обратиться к нему и как к false, просто функция вернула false. Во втором случае, свойство "назвали" объектом. Мдо, круто) – Олег Архипов Mar 20 '12 at 15:44
  • 1
    @Sh4dow - никто не заставляет писать такой бред, но то, что подобные конструкции возможны и краткость их записи не может не умилять. –  Mar 20 '12 at 15:49
  • @Construct найн, в первом случае ключом тоже был объект (n.prototype === Function). Т.е. function(){} - объект, (function(){})() - результат функции. obj[false] выдаст undefined)

    @AlexWindHope, ну не знаю... С одной стороны, "может быть когда-нибудь" этому найдется применение, а сейчас это выглядит сложение строки с объектом и деление на массив.

    – Sh4dow Mar 20 '12 at 17:36
  • От идиотизма ни один язык программирования не застрахует. Как по мне - приведенный вами код лишь демонстрирует то, насколько гибок язык, но никак не то, насколько он страшен. –  Mar 20 '12 at 17:48

5 Answers5

20

Для начала - немного теории. Эту ИМХО глупость, в свое время, начал 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'е, возможно, где-то, это удобно и практикуется большинством, тогда конечно - юзайте на здоровье (спасибо кэп).

  • А мне нравится такое поведение. Использование id как объекта в Javascript-коде представляется очень естественным обращением к элементам. Я, конечно, пишу на JavaScript не для Web, а для реализации логики QML-интерфейсов, там обращение по id архиудобно и никаких проблем не возникает. Проводя аналогию, подозреваю, удобство доступа по id проявится при реализации интерактива на холсте (canvas) HTML5.

    По поводу примера думаю, что его недостаток не в обращении по id, а в обращении к функции глобально. При использовании пространств имен, описанная ситуация невозможна. Есть ли другие примеры проблем

    – northerner Mar 20 '12 at 06:51
  • @northerner - ваши подозрения ничем не подкованы, вообще причем тут html canvas?.. Я очень сильно увлекаюсь этой технологией и, смею вас заверить, код работы с DOM'ом ~= 0, соответственно реально не понял о чем вы.

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

    Конечно если вы пишите что-то сами от и до - пишите как вам удобно, тут абсолютно фиолетово, я писал в контексте норм масштабов и команды

    –  Mar 20 '12 at 07:18
  • А ненравиться мне такое поведение потому, что в JS и так все выстроено вокруг глобальной области, но нет-же, все мало, даешь больше -_- –  Mar 20 '12 at 07:21
  • И вообще - функционал сомнительный, нужен мягко говоря не каждому и, мягко говоря не всегда, более того - это, без проблем, можно реализовать самому. Соответственно я вообще не понимаю кто утвердил эту (censore). –  Mar 20 '12 at 07:25
  • Вот этот ответ я и ждал! @AlexWindHope Спасибо! – Palmervan Mar 20 '12 at 07:28
  • Всегда пожалуйста –  Mar 20 '12 at 07:30
  • @AlexWindHope, мои подозрения основаны на двух моментах:
    1. Существует как минимум одна реализация JavaScript, в которой вообще нет функции getElementById, доступ к свойствам и методам элементов обеспечивается через id - в QML. Но возможностей превратить код в спагетти в QML гораздо меньше, чем в браузерном JavaScript: модификация глобального объекта не допускается, любой код должен быть упакован в пространства имен.
    2. И вот в стандарте HTML5 также разрешают прямое обращение. Протолкнуть что-то в стандарт очень сложно, нужна поддержка нескольких членов комитета, а они там далеко не дураки
    – northerner Mar 20 '12 at 15:24
  • Вопрос я читал. И комментарии тоже читал. Они в основном резко отрицательные. И я не понимаю, почему от этого нововведения в HTML от W3C должно стать всё плохо и использовать его нельзя, если существует QML от Nokia, где всегда так было, все хорошо и не использовать это просто невозможно. Мне на самом деле хотелось вовлечь всех участников обсуждения в дискуссию. Просто очень много отрицательных оценок в комментариях и мало фактов. У Вас в ответе по крайней мере анализ есть.

    Ладно, забейте, наверное, лучше всего подождать - время покажет, полезная это фича или ненужная.

    – northerner Mar 20 '12 at 16:26
12

Обсуждение на 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

Yura Ivanov
  • 26,491
  • @Yura Ivanov хороший ответ, а главное вместительный и понятный! Спасибо.

    На стаке увидел от части в вопросе подобно когдато моему тут

    – Palmervan Mar 19 '12 at 21:40
8

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

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

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

Alex Silaev
  • 4,042
  • 1
  • 17
  • 26
  • Суть в том что от стандарного применения я отказываться не собирался... Перебирая методы подхода и прочее, выяснил то что это все работает, вот и стало интересно о существовании подводных камней... – Palmervan Mar 19 '12 at 15:51
  • да к стате, если этот метож работает в IE6 и самом древнем Firefox не говоря уже о опере, вероятность того что этот метод будет отклонен аналогичкна тому же getElementById. Но повтоюсь что оспаривать ничего не берусь! – Palmervan Mar 19 '12 at 18:02
  • Смотрите оф доку;) – Alex Silaev Mar 19 '12 at 18:19
  • точну ссылку плз) – Palmervan Mar 19 '12 at 18:21
  • у меня кста есть товарищ, нетлешный js'ер, ему еще напишу! ну уперты я) благодаря упертости имею достижения!) – Palmervan Mar 19 '12 at 18:23
  • Занимаюсь js чуть больше 10лет, из них 6 - профессионально. Никогда не использовал такие конструкции и не буду. Хотите писать так - нет проблем, но это плохой код) – Alex Silaev Mar 19 '12 at 18:30
  • developer.mozilla.org/en/JavaScript/Reference - это в фф. По всем остальным ищите в гугле)) – Alex Silaev Mar 19 '12 at 18:35
2

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

<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, которую мы успешно переписали!
Ну вот как-то так. Даже мой, приведенный тут случай, можно считать "подводным камнем".

Anton Mukhin
  • 5,535
  • 9
  • 53
  • 92
  • 1
    @Антон Мухин Вы так ответили как будто я пропагандирую данный подход... Я собираю информацию на предмет подхода а не рву кишки что я изобрел что-то супер мега необходимое для каждого web мудрильщика!

    Из слова мудрильщика - кто желает может убрать букву р

    – Palmervan Mar 19 '12 at 18:31
  • Вот, я привел еще один из подводных камней... :) – Anton Mukhin Mar 19 '12 at 18:52
  • 2
    Да и вот, на ваше

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

    var mydiv = document.getElementById("mydiv"); и потом к ней обращаться, если обращение можно сделать сразу к mydiv? Поясните!

    прояснил также некоторую ситуацию, "зачем".

    – Anton Mukhin Mar 19 '12 at 18:53
  • 1
    Поддерживаю этот ответ. Я не думаю, что обращение по id непосредственно - грязный хак, недокументированная фича и будет вырезана :) Сам пишу на QML, который тоже скриптуется JavaScript - там использование id элементов как объектов JavaScript является основной рекомендуемой практикой. Но как показано на примерах getElementById() универсален и может использоваться, если напрямую по id не обратиться из-за особенностей синтаксиса или если имя id задано переменной. – northerner Mar 19 '12 at 19:07
0

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

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

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

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

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

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

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

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

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

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

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

Palmervan
  • 9,350
  • Всех знаний не перзнаешь, всех тонкостей не учтешь, всех методов не переметодишь! В некоторых случаях, - одни приемы полезны, в других случаях - другие. Все зависит от конкретной задачи! Тут, @northerner просветил что, оказывается, в некоторых случаях приведенный вами пример, даже рекомендуем!
    Но, глядя на ваше высказывание, что вы пытаетесь исключить мишуру и лишние знаки... Я думаю, что этим не стоит злоупотреблять потому, что, как мне думается, может ухудшить читабельность кода.
    – Anton Mukhin Mar 19 '12 at 19:42
  • @Антон Мухин - всего, действительно, не узнаешь, но нужно к этому стремиться.

    Это несомненно, не только может, но и ухудшит читабельность кода

    –  Mar 19 '12 at 23:29