1. Суть в разделении декларативного HTML от императивного JS.
Плохо:
Хорошо:
Код: Выделить всё
<div id="banner"></div>
<script>
document.getElementById('banner').onclick=function(){
alert('clicked!');
}
</script>
Если объявлять обработчик прямо в атрибуте тега, то можно прямо тама написать код функции: alert('clicked');, -- и это нормально, если не брать во внимание, что в принципе объявлять обработчики в атрибутах -- плохо.
Функция, присвоенная .onclick дом-элемента вызывается при совершении события click, но даже если попытаться просто присвоить alert:
Код: Выделить всё
document.getElementById('banner').onclick=alert
, то указать аргументы функции alert не удастся, то есть функция будет вызвана без аргументов (по крайней мере, без нужного нам).
Что бы это обойти, мы либо создаём именованую функцию:
и присваеваем её свойству onclick:
Код: Выделить всё
document.getElementById('banner').onclick=handler
, либо создаём безымянную функцию, сразу же присваиваем её свойству (наверху).
Т. е. на самом деле function(){} создаёт объект Функция и возвращает ссылку на неё.
function name(){} так же создаёт функцию, но при этом она именована: name.name //name
и name уже ссылается на неё.
Важно понимать, что функции в JS -- такие же объекты, как и любые другие:
Код: Выделить всё
function foo(){
//...
}
foo.prop="bar";
foo.prop; //bar
Так же важно понимать, что функции в JS, в отличие от многих других языков могут быть созданы в runtime, и с этим возникает несколько интересностей:
все объекты в области видимости, в которой создаётся функция, доступны во время исполнения функции
Код: Выделить всё
var bar="a";
var foo=function(){
return bar;
}
bar="b";
foo(); //b!!!!!
в создаваемой функции создаётся своя, новая, другая область видимости, объекты в которой недоступны из родительской, но не наоборот!
Так же следует понимать, что объект не может быть присвоен какой-нибудь переменной. Вообще.
Даже если прямо написать var variable=new SomeInterestingClass();, то будет создан объект без имени, будет взят адрес и присвоен variable, а т. к. операции разыменовывания var variable=*(new SomeInterestingClass()); в JS нема, то его не разыменуешь (плюсишник знает, что new берёт адрес, я же далее не знаю, но знаю, что в JS оператор new создаёт новый анонимный объект new Object() и устанваливает его в качестве контекста вызова функции SomeInterestingClass так, что он доступен из неё по ссылке this).
Код: Выделить всё
var obj1=new Object();
var obj2=obj1;
obj1.bar="foo";
console.log(obj1.bar);
console.log(obj2.bar);
obj2.bar="oops";
console.log(obj1.bar);
console.log(obj2.bar);
Вывод: foo foo oops oops.
Объекты надо копировать (когда надо. А когда надо?) явно.
К скалярам это не относится.
2. document.onload не следует использовать. Вообще.
Везде следует использовать window.onload. При этом важно понимать, что это событие произойдёт после подгрузки ВЕГО, что только можно.
Это -- наиболее безопасное и раннее время загрузки, однако если нужно ещё раньше (для быстрее), то в большинстве случаев, когда уже надо оперировать DOM, можно ждать события DOMContentReady. Обработчик добавляется с помощью addEventListener().