Javascript-форум (https://javascript.ru/forum/)
-   Общие вопросы Javascript (https://javascript.ru/forum/misc/)
-   -   Ошибка в учебнике (https://javascript.ru/forum/misc/53544-oshibka-v-uchebnike.html)

freee 08.02.2015 13:45

Ошибка в учебнике
 
Не знаю, куда запотсить, перенесите тему, если чо.

Вот тут
http://learn.javascript.ru/searching-elements-dom
Цитата:

Важно, что в документе может быть только один элемент с данным id. Конечно, можно нарушить это правило и создать много элементов с одинаковым идентификатором, но в таком случае поведение метода getElementById будет непредсказуемым.
естественно, семантически неверно использовать неуникальные идентификаторы, но технически, данное утверждение, о непредсказуемом поведении, по-моему, ошибочно. Во всяком случае, я ни разу не встречал UB в широко поддерживаемых на данный момент браузерах(в том числе ie8). Всегда возвращается первый элемент.
<html>
<head>
</head>
<body>

<div id="foo">foo</div>
<div id="foo">bar</div>
<div id="foo">baz</div>

<script>
alert(document.getElementById("foo").innerHTML)
</script>

</body>
</html>


И вот еще что, следом там идет
Цитата:

Браузер автоматически создаёт переменные для элементов с id, через которые к ним можно обратиться.

...

Это поведение соответствует стандарту. Оно существует, в первую очередь, для совместимости, как осколок далёкого прошлого.
это сугубое ИМХО, но это не "осколок", а вполне обоснованая фича, сделанная для удобства программиста, которая позволяет избежать лишней писанины типа myelement=document.getElementById("element"). К сожалению, в большинстве случаев использется именно последнее, а это ни что иное, как тупое дублирование кода.
BTW, может кто в курсе, что говорит последний стандарт по поводу данного поведения?

ruslan_mart 08.02.2015 15:17

freee, фишка с ID не везде работает, поэтому лучше всегда писать так:
var test = document.getElementById('test');

freee 08.02.2015 15:22

Цитата:

Сообщение от Ruslan_xDD
фишка с ID не везде работает, поэтому лучше всегда писать так:

А где не работает? Я проверял в ff, v8, и ie8. На остальные, в принципе, можно забить, в большинстве случаев. Правда, работа немного отличается, при дублировании id.

Erolast 08.02.2015 16:11

Цитата:

это сугубое ИМХО, но это не "осколок", а вполне обоснованая фича, сделанная для удобства программиста, которая позволяет избежать лишней писанины типа myelement=document.getElementById("element"). К сожалению, в большинстве случаев использется именно последнее, а это ни что иное, как тупое дублирование кода.
Это засирание глобала, нарушение инкапсуляции. В жопу.

freee 08.02.2015 16:20

Цитата:

Сообщение от Erolast
засирание глобала, нарушение инкапсуляции

В таком случае в начале каждого скрипта удаляй все имена которые соответствуют идентификаторам в документе.

И, при чем тут инкапсуляция?

ruslan_mart 08.02.2015 16:27

freee, я как-то забыл записать элемент в переменную, а потом полдня гадал почему в FF не работает. :)

Erolast 08.02.2015 16:40

Цитата:

И, при чем тут инкапсуляция?
При том, что засирание глобала и есть нарушение инкапсуляции.
Цитата:

В таком случае в начале каждого скрипта удаляй все имена которые соответствуют идентификаторам в документе.
Вот именно. Какого хрена я должен при написании контроллера оглядываться на верстку представления?

ruslan_mart 08.02.2015 16:53

Erolast, ну а что теперь сделать? Может ещё неиспользуемые методы API удалять? :)

Erolast 08.02.2015 17:04

А такие есть?

freee 08.02.2015 17:14

Цитата:

Сообщение от Erolast
А такие есть?

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

Aetae 08.02.2015 17:17

freee,
1. UB на то и UB, что оно Undefined. Во всех существующих браузерах вернётся первый элемент с таким id, да. НО совершенно не факт что завтра не появится новый браузер который будет возвращать последний. Или вообще рандомный. И никто ему не запретит так делать ибо UB.:)
Потому не вижу смысла удалять это уточнение.

2. Исторически вынесение идентификаторов в глобал изначально было стандартом, потом было исключено из стандарта и вроде даже(не уверен) из некоторых браузеров, и с html5 вернулось в стандарт.
Мнения на этот счёт разные, однако бесконтрольное засорение глобальной области видимости среди js-программистов считается моветоном. Некоторые даже специально используют идентификаторы содержащие символы невозможные в переменных, дабы избежать замусоривания. Например:
<input type="text" id=":textfield">

Так или иначе я бы не назвал это "ошибками в учебнике". Максимум недостаточная освещённость вопроса и то спорно.

freee 08.02.2015 17:28

Цитата:

Сообщение от Aetae
Некоторые даже специально используют идентификаторы содержащие символы невозможные в переменных, дабы избежать замусоривания. Например:

Возможно, это ведет к тормозам, так как на уровне реализации эти случаи обрабатываются, видимо, отдельно. Неизвестно, какую цепочку ифов проходит каждое такое "объявление"
Кроме того, поиски getElementById, возможно, используют все те же глобальные переменные. А querySelector с решеткой использует getElementById... И так далее, дальше в лес - больше дров.

Aetae 08.02.2015 17:37

freee, не там тормоза ищите. getElementById работает очень быстро. Это не может стать бутылочным горлышком ни в одном разумном случае.:)

freee 08.02.2015 17:43

Aetae,
Кстати, нет, щас проверил, никуда они не деваются, они просто недоступны в литеральной нотации, так что это вдвойне глупо
<html>
<head>
</head>
<body>
 
<div id=":foo">foo</div>
 
<script>

alert(window[":foo"])



</script>
 
</body>
</html>

freee 08.02.2015 17:47

Цитата:

Сообщение от Aetae
getElementById работает очень быстро

Я предполагаю, что он работает быстро как раз потому, что ему не надо производить каждый раз поиск по документу, он просто берет переменную из глобала, то есть вызов document.getElementById("element") эквивалентен вызову window["element"], или даже просто element. Это и есть причина его быстроты. Но это всего лишь предположение.:)

Aetae 08.02.2015 17:52

freee, оно не верно. В глобале лишь ещё одна ссылка.

P.S. Не надо "гадать". Никогда. Интересно как работает - смотри спецификацию или код движка.

freee 08.02.2015 17:58

Цитата:

Сообщение от Aetae
оно не верно. В глобале лишь ещё одна ссылка.

Я не понял, что не верно? В глобале одна ссылка, да, в данном случае, ":foo", как это противоречит тому что я сказал?

Aetae 08.02.2015 18:06

freee, всё сложнее и проще. Нет никакого смысла нативному коду лезть в javascript'овский глобал.

freee 08.02.2015 18:13

Цитата:

Сообщение от Aetae
freee, всё сложнее и проще. Нет никакого смысла нативному коду лезть в javascript'овский глобал.

document.getElementById вызывается из JS. Для поиска элемента у него два варианта: дернуть какой то нативный модуль, чтобы тот произвел поиск по документу (условно говоря), и вернул ему результат. Это, сконей всего, дорогая операция, так как лишний рантайм. Другой вариант -- просто воспользоваться готовой ссылкой в js, это ничего не стоит, поскольку получаем мы в итоге все ту же ссылку, выбор, по-моему, очевиден.

Aetae 08.02.2015 18:22

Ваше представление о том как всё работает крайне ошибочно и наивно. Дискутировать никакого желания у меня нет.
Лет через пять, если не завяжете с этим делом, будете со смехом читать свои текущие посты.

MallSerg 09.02.2015 02:31

Похоже у foo новый ник.
Снова троллингом развлекается )).

ruslan_mart 09.02.2015 07:00

MallSerg, действительно, IP совпадают.

freee, очередной аккаунт foo/Krutoy/losos10, бан навсегда.

Erolast 09.02.2015 09:33

Да ладно, на этот раз же вполне адекватен был.

ruslan_mart 09.02.2015 11:21

Erolast, на долго ли? :) Создание фейкового аккаунта - уже нарушение.

MallSerg 09.02.2015 17:12

Бан это уже слишком.
на личности он не переходил и вел себя хорошо
без foo форум становится скучным =(

ruslan_mart 09.02.2015 17:35

MallSerg, по твоей логике, я могу смело нарушать правила форума, и в случае бана - просто создавать новый аккаунт. :)
Что касается freee, то он всё прекрасно знает, а темы с глупыми вопросами создаёт, чтобы развести тут очередной холивар. Если бы вёл себя адекватно, то никто бы даже и не заметил, что это foo/Krutoy/losos100.


Часовой пояс GMT +3, время: 12:17.