Javascript-форум (https://javascript.ru/forum/)
-   Общие вопросы Javascript (https://javascript.ru/forum/misc/)
-   -   оброботка события load (https://javascript.ru/forum/misc/1809-obrobotka-sobytiya-load.html)

clgs 19.09.2008 14:41

оброботка события load
 
Доброе время суток!
Подскажите как оброботать событие load не помешая в <body> или еще куда либо, только по средством JS?

P.S. Только заумные скрипты и фразы не кидать. Я только начал учить JS.

Заранее благадарен clgs.

Dmitry A. Soshnikov 19.09.2008 16:22

clgs, самый простой вариант:

window.onload = function() {
  // code here
};


Однако, этот код уничтожит старый onload, если он был (например, прописанный в теге body), поэтому обычно запоминают старый onload, а в своей функции вызывают этот старый onload и затем уже свой код.

P.S.: сегодня уже давно обрабатывают onDOMContentLoaded (событие наступает, когда построенно дерево DOM; порой, намного раньше, чем onload, т.к. onload наступит, когда вся страница (включая большие изображения) бедет загружена) и его эмуляции для браузеров, которые пока не поддерживают это событие.

ZoNT 19.09.2008 16:52

function addEvent(e,t,f){
		if (e.addEventListener) e.addEventListener(t, f, false);
		else if (e.attachEvent) e.attachEvent('on'+t, f)
	}
	function removeEvent(e,t,f){
		if (e.removeEventListener) e.removeEventListener(t, f, false);
		else if (e.detachEvent) e.detachEvent('on'+t, f)
	}

addEvent(window, 'load', any_func);
removeEvent(window, 'load', any_func);

Dmitry A. Soshnikov 19.09.2008 17:17

ZoNT, тогда уж оптимизировать до конца. Какой смысл каждый раз проверять, какую обработку юзать - "add..." или "attach..."? Лучше проверить это один раз при инициализации и создать свою функцию, в зависимости от браузера.

ZoNT 19.09.2008 18:06

флаг в руки! Только это будет вешаться один раз и оптимизаия выйдет ненужная. При оптимизации по скорости ухудшится ситуация по размеру. Надо смотреть, что требуется. Если требуется один раз повесить обработчик и оди раз снять, то надо уменьшать объём. Если надо 20 раз в секунду рвешать/снимать обработчики ( :D ), тогда заводи быстродействующие браузерозависимые функции.

Dmitry A. Soshnikov 19.09.2008 18:15

ZoNT, че-т я не верю, что универсальная функция добавления/удаления слушателя (где window - это такой же слушатель) у тебя используется в коде меньше, чем 10 раз :D Я всего лишь привел информацию; оптимизировать или нет - твое право =)

Цитата:

Сообщение от ZoNT
браузерозависимые функции

функцию (она одна будет, единственное отличие - обработчик будет назначаться сразу - безо всяких проверок каждый раз)

ZoNT 19.09.2008 18:17

у меня она оптимизированна. По размеру. Так как по времени она вызывается НЕ ПОДРЯД (!!!) 10 раз, то и тормозов никогда не будет.

ZoNT 19.09.2008 18:18

гм... Вообще, если честно, то нашёл где используется максимум по два раза добавление/удаление...

Dmitry A. Soshnikov 19.09.2008 18:32

Цитата:

Сообщение от ZoNT
По размеру.

в данном случае, оптимизация по размеру - вторична (файл подгрузился и все, а в случае неоптимизации по скорости - постоянно будет уходить лишнее время на if-else if)

Цитата:

Сообщение от ZoNT
НЕ ПОДРЯД (!!!) 10 раз

да какая разница =) все равно время теряешь на проверки )

ZoNT 19.09.2008 18:35

ну, 1мс*10 = 10мс. Мне не жалко 10мс на весь просмотр страницы, так как погрешности загрузки страницы больше 10мс.

Ха-ха-ха. Файл подгрузился и всё. А если стоит антикэш и файл отдаётся более чем миллиард раз в сутки??? 100байт*1000 000 000 = 93 гига трафика в сутки!

Dmitry A. Soshnikov 19.09.2008 18:39

Цитата:

Сообщение от ZoNT
Ха-ха-ха

ZoNT, бессмысленный неадекват начинается =) почитай об оптимизации JS. Закончим на этом (ты конструктивные советы не умеешь воспринимать ;)).

Octane 19.09.2008 18:47

Можно немного сократить условие :-)
function addEvent(e,t,f){
  if (e.addEventListener) e.addEventListener(t, f, false);
  //@cc_on e.attachEvent('on'+t, f);
}

function removeEvent(e,t,f){
  if (e.removeEventListener) e.removeEventListener(t, f, false);
  //@cc_on e.detachEvent('on'+t, f);
}

IE8b2 так и не поддерживает «addEventListener», и думаю не будет поддерживать, поэтому вроде должно корректно работать везде.

ZoNT 19.09.2008 18:56

Цитата:

Сообщение от Dmitry A. Soshnikov (Сообщение 6056)
ZoNT, бессмысленный неадекват начинается =) почитай об оптимизации JS. Закончим на этом (ты конструктивные советы не умеешь воспринимать ;)).

Фигасе, бессмысленный неадекват. Я тебе описал реальную ситуацию, которая работает на данный момент у нас в фирме...

Dmitry A. Soshnikov 19.09.2008 19:29

Цитата:

Сообщение от ZoNT
Фигасе, бессмысленный неадекват

да ладно, не парься =) этим я хотел сказать, что ты рассуждаешь о 93 гигах трафа, когда в код добавится пару строк; и то - после обфускации разница будет вообще микроскопической.

Octane, да, можно и условный комментарий. На всякий случай, приведу вариант, о котором говорил выше (необфусцированный, естественно):

var registerEvent = (function() {
  if (document.addEventListener) {
    return function(element, eventName, handler, useCapture) {
      return element.addEventListener(eventName, handler, useCapture);
    };
  } else if (document.attachEvent) {
    return function(element, eventName, handler) {
      return element.attachEvent('on' + eventName, handler);
    };
  }
})();

var unRegisterEvent = (function() {
  if (document.removeEventListener) {
    return function(element, eventName, handler, useCapture) {
      return element.removeEventListener(eventName, handler, useCapture);
    };
  } else if (document.detachEvent) {
    return function(element, eventName, handler) {
      return element.detachEvent('on' + eventName, handler);
    };
  }
})();

ZoNT 19.09.2008 21:00

ну и сравни по размеру:
function addEvent(e,t,f){if(e.addEventListener)e.addEventListener(t,f,false);else e.attachEvent('on'+t,f)}
function removeEvent(e,t,f){if(e.removeEventListener)e.removeEventListener(t,f,false);else e.detachEvent('on'+t,f)}

и
var addEvent=(function(){if(document.addEventListener)return function(e,n,h,u){e.addEventListener(n,h,u)};else return function(e,n,h){e.attachEvent('on'+n,h)}})();
var removeEvent=(function(){if(document.removeEventListener)return function(e,n,h,u){e.removeEventListener(n,h,u)};else return function(e,n,h){e.detachEvent('on'+n, h)}})();

338(твой)
223(мой)
Итого: 115 байт (более 100 байт).
(115 * 1 000 000 000)/1073741824 = 107 гигов/сутки.

Dmitry A. Soshnikov 19.09.2008 21:25

ZoNT, мелочи это все =) Ну как знаешь, повторю - я привел вариант оптимизации, принять или нет - это уже твое дело.

А по скорости тесты провел?

ZoNT 19.09.2008 21:32

Я тебе про оптимизацию по размеру, он мне про баню...
Выигрывая 10мс на стороне клиента мы попадаем на 107 гигов ежедневного трафика.

Ты линукс уважаешь? А ты знаешь что сейчас ядро линукса собирается с оптимизацией по размеру, а не по скорости?

Dmitry A. Soshnikov 19.09.2008 21:56

Цитата:

Сообщение от ZoNT
Я тебе про оптимизацию по размеру, он мне про баню...

Про оптимизацию по размеру это ты парировал уже позже (чтобы как-то оправдать лишние if'ы-else'ы), я изначально говорил об оптимизации по скорости.

По твоим рассказам, твой код должен тогда выглядеть примерно так (если на счету уже байты):

var d = document, 
b = 'EventListener',
c = 'add',
e = 'remove',
f = 'attach',
g = 'detach';

if(d[c+b])q[c+b](...); 

// и т.д.

// что ж ты так не пишешь, а? Если у вас так все сложно с трафом =)


Еще пример - глубокое DOM-дерево. Берем коллекцию (в самой глубине) из n-ого кол-ва элементов, проходимся циклом (ты, как я понимаю, будешь использовать второй вариант, да? (ну конечно, целых 9 байт текста тратится на объявление переменной length ;))):

// быстрый 
for (var k = 0, length = коллекция.length; k < length; k++) { // code }

// медленный (каждый раз вычисляется значение
// свойства length, перед этим из DOM-дерева получается
// сама колекция - это тоже время)
for (var k = 0; k < коллекция.length; k++) { // code }



Цитата:

Сообщение от ZoNT
Ты линукс уважаешь?

ага

Цитата:

Сообщение от ZoNT
А ты знаешь что сейчас ядро линукса собирается с оптимизацией по размеру, а не по скорости?

неа (но если это факт - буду знать)

ZoNT 19.09.2008 22:14

for (var k = 0, l=коллекция.length; k < l; k ++) - итого 3 лишних байта.

Но эта не тот случай, на котором надо экономить. Ты сильно утрируешь:
коллекция будет перебираться намного дольше, чем выполняется навешивание обработчика событий. Плюс я никогда не навешиваю обработку событий в цикле. Если есть куча элементов, которым надо навесить обработчик в цикле, значит можно этот обработчик навесить 1 раз на парент и немного откорректировать код.

Андрей Параничев 19.09.2008 22:23

У больших проектов (1 000 000 000 хостов) есть проблемы и побольше, чем 107 гигов траффика в сутки. Да и вообще обсуждается сферический сервер в вакууме, ведь при стольких хостах исходящий траффик настолько велик, что лучше задумываться об оптимизации скорости на клиенте, чем о лишних байтах.

Dmitry A. Soshnikov 19.09.2008 22:24

Цитата:

Сообщение от ZoNT
Если есть куча элементов, которым надо навесить обработчик в цикле, значит можно этот обработчик навесить 1 раз на парент и немного откорректировать код.

это и так понятно, и все так делают, не нужно это аргументом приводить

Цитата:

Сообщение от ZoNT
for (var k = 0, l=коллекция.length; k < l; k ++) - итого 3 лишних байта.

Вероятно, у тебя length будет использоваться неоднократно, поэтому ты его выше где вынесешь (var a = 'length'; ): =)

for (var k = 0, l=коллекция[a]; k < l; k ++) - итого, даже при двух подобных циклах в коде, ты сэкономишь 5 байт =) Только тогда весь код так пиши (как я предлагал в предыдущем посте var d = document; var a = 'add'; )

Ладно, все, спор бессмысленный, завершимся на этом.

ZoNT 19.09.2008 22:29

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

EugenyK 26.10.2008 22:43

Dmitry A. Soshnikov,
объясни пожалуйста, почему определение функции registerEvent
через скобки (function(){ ... })() будет "кэшировать" if-else и где про это можно почитать подробнее?

Dmitry A. Soshnikov 27.10.2008 00:07

EugenyK, все просто:

var f = function () {
  if (известныеДанные) {
    alert(1);
  } else {
    alert(2);
  }
};


При вызове данной функции f() всегда будет выполняться if (это очевидно).

Далее, известно, что функцию можно вызвать сразу после объявления:

(function a () { // объявляем функцию
  alert(3);
})(); // и тут же ее вызваем


Кстати, имя функции в данном случае опционально.

В JavaScript функция является объектом, ее можно вернуть, присвоить и т.д. - см. первый пример - переменной f присваивается анонимная функция, которая потом доступна для вызова через имя переменной - f(). Т.е. первый пример можно "перефразировать" так (мы делаем внешнюю оболочку из анонимной функции, которая вызывается сразу же после своего определения и возвращает другую анонимную функцию):

var f = (function () {
  return function () {
    if (известныеДанные) {
      alert(1);
    } else {
      alert(2);
    }
  }
})();


Таким образов вызов нынешней функции f() ничем не отличается от первой. Но, естественно, никакого смысла в такой перефразировке нет - мы только лишь создали дополнительное действием по вызову внешней анонимной функции. Однако, (сейчас пойдет ответ на твой вопрос :)): если мы вынесем if-else в определение внешней оболочки (при условии, что данные для проверки известны заранее и неизменны), то проверка выполнится единожды - когда функция-оболочка вызовется сразу же после определения. В проверках же нужно вернуть функции уже без проверок, - просто выполняющих свои действия:

var f = (function () {
  if (известныеДанные) {
    return function () {
      alert(1);
    };
  } else {
    return function () {
      alert(2);
    };
  }
})();


Теперь f - это либо function () {alert(1)}; либо function () {alert(2)};, и определилось это при инициализации - один раз. Сам вызов f() уже никаких проверок не делает.

EugenyK 28.10.2008 11:04

Большое спасибо! Теперь всё ясно.

alexKniaz 28.10.2008 18:03

Цитата:

100байт*1000 000 000 = 93 гига трафика в сутки!
Ну чё мелочиться??? 1 секунда ничего не даст!!!! ВЫВОД - ОПТИМИЗИРУЙТЕ РАЗМЕР!!!!


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