Имеется функция, которой передается массив и строковая переменная; Функция должна работать в цикле, выводя содержимое массива построчно с определенным интервалом(30-100мс); Выглядит примерно так: [js] function submenuInsert(submenuArray, i, id) { if (i < submenuArray.length) { document.getElementById(id).appendChild(submenuArray); i++; setTimeout("submenuInsert(submenuArray, i, id)", 60); } }[/js] Во втором цикле, вызванном с помощью setTimeout, переменные имеют значение undefined; Пробовал писать и так: setTimeout("submenuInsert()", 60, submenuArray, i, id); Что можно придумать, не используя глобальную переменную? Вызовов этой функции может быть несколько раз подряд, с разными параметрами... Пробовал создать обьект(обьект создается конструктором внутри другой функции), та же самая история - только первый проход нормально, потом обнуление... опять же глобальный обьект не подходит...
У функции setTimeout 2 параметра - наименование функции и время. Без объекта тут не обойтись. А передавать его нужно так: [js] setTimeout("submenuInsert("+objectName+")", 60);[/js]
HTML: <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> <html> <head> <title>123</title> <script type="text/javascript" src="js/core.js"></script> <script type="text/javascript"> function submenuInsert(submenuArray, i, id) { this.length = submenuArray.length; this.timer = function() { $(id).appendChild(submenuArray[i++]); if (i < this.length) setTimeout(this.timer, 60); } this.timer(); } </script> </head> <body> <div id="parent"></div> <script type="text/javascript"> var submenu = new Array(); for (var i =0; i < 20; i++) { var div = create_element(null, 'div'); create_txt(div, 'submenu '+i); submenu.push(div); } submenuInsert(submenu, 0, 'parent'); </script> </body> core.js: [js]/* Сокращение document.getElementById */ function $(id) { return document.getElementById(id); } /* Создает текстовый нод с содержанием content */ function create_txt(parent, content) { var txt = document.createTextNode(content); parent.appendChild(txt); return txt; } /* Создает элемент name с атрибутами atts * Если parent != null добавляет к нему элемент */ function create_element(parent, name, atts) { var el = document.createElement(name); for (var aname in atts) el.setAttribute(aname, atts[aname]); if (parent != null) parent.appendChild(el); return el; }[/js]
У функции setTimeout много парметров и по стандарту надо было бы использовать так: [js]setTimeout(submenuInsert, 60, submenuArray, i, id);[/js] Но IE имеет свой формат этой функции: В итоге работать надо исключительно через объект иначе где-нибудь работать не будет.
у сеттаймаут есть необязательные параметры, которые должны передаться в функцию, если верить справочнику... http://experiment.net.ru/js1/?f=window.htm#1203758 А проблема с параметрами у меня в том, что они берутся с ответа сервера, на каждый вызов функции должна создаваться своя переменная, которая по окончании работы функции должна уничтожаться...
У меня используется AJAX, ответ сервера я должен вывести построчно, с временным интервалом... Пользователь может открыть несколько субменю и скрипт не должен ждать, пока отрисуется только-что открытое подменю чтоб начать выводить следующее... Эт значит, что одновременно может быть несколько вызовов функции. Голову ломаю, как сделать чтоб каждая имела свои параметры, не смешивающиеся с параметрами другого вызова... так понятнее?))
А я ведь не так давно почти любил IE)) Щас сижу на FF и не понимаю, как IE мог так меня привлекать... Еще б с винды слезть для полного счастья...
эт был перевод того что я сказал выше, на тот момент я просто не заметил поста с кодом) По твоему коду: работает идеально, но вообще не могу понять логику работы(( Пока факт работы будет аксиомой)
А логика простая. 1. Добавляем чайлда (и заодно увеличиваем итератор) 2. Если есть еще чайлды в массиве ставим таймаут на себя Вся эта хрень внутри объекта только для того, чтобы не передавать параметры в функцию… т.е. параметры глобальные для локального контекста (во завернул )
Да это-то понятно) Просто насмотревшись на работу кода , ожидал что setTimeout отложит выполнение объекта-функции(как правильно называется-то?) timer, а функция submenuInsert не будет дожидаться этого момента и благополучно завершится... Почему происходит не так - это как раз и не понимаю) Зы: Как это было в моем примере - функция завершилась, и когда срок задержки по таймауту(60мс) закончился, переменных для вставки уже не было, отсюда возникало undefined...
Она завершается. сразу же после первого выполнения метода timer() Просто тут надо понимать, что setTimeout не эквивалентно заданию паузы. А переменные живы пока жив объект, а жив он пока внутри него что-то делается (потом сборщик мусора его убьет)
Сегодня обнаружил, работает везде... кроме IE... показывает ошибку "Object doesn't support this action" Ненавижу IE... ругается на метод timer... тока на какое конкретно действие - хз... похоже присвоение анонимной функции...
Нет, на переопределение своства length объекта функции. Поменяй length на l или еще на что-нибудь: все будет работать.
eduha я что-то подобное пробовал уже, переменные принимают значение undefined... вариант Гусева удобный и, главное, действенный. AlexGousev хм... и точно! вот чем не люблю JS, так это тем что его сложно воспринимать после php... функция, как обьект, ну никак не укладывается у меня в голове) Да и отсутствие объявления классов напрягает)
вот за что не люблю пхп, так это за то, что в нём нельзя сделать так: [js]Function.prototype.$bind= function( obj, params ){ var func= this; return function( ){ return func.apply( obj, params || arguments ); } } Function.prototype.$timeout= function( time ){ if( !document ) return; var func= this; var win= /On/i.test( document.designMode ) ? parent : window; // for FF win.setTimeout( function( ){ if( func( ) ) func.$timeout( time ); }, time ) return this; } submenuInsert.$bind( null, [ submenuArray, i, id ] ).$timeout( 60 ); [/js]
гы, красиво завернул) не объяснишь, как вот эта строчка работает? /On/i.test() откуда берется и что делает непонятно [js]var win= /On/i.test( document.designMode ) ? parent : window; // for FF[/js]