Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > JavaScript: Общие вопросы > Передача в setTimeout ссылки на this


Автор: dm9 28.8.2006, 17:19
Здравствуйте.

Что-то долго пытался обрисовать тему в словах, но не получилось smile Так что даю код, а что он делает — из него самого должно быть понятно.

Код

<html>
<head>
<title>test</title>
</head>
<body>
<script type="text/javascript">
function MyObject(inputId) {
    this.input = document.getElementById(inputId);
}
MyObject.prototype = {
    GoDots : function() {
        this.input.value += "-";
        setTimeout("obj.GoDots()", 200); // BAD!
    },
    Start : function() {
        this.GoDots();
    }
}
</script>
<div>
    <input type="text" size="50" id="inp" />
    <button onclick="obj.Start()">Start</button>
</div>
<script type="text/javascript">
    var obj = new MyObject("inp");
</script>
</body>
</html>


Вопрос в том, как избавиться от "obj" в 13-й строке, передав вместо "obj" что-то вроде "this".
Или, возможно, мой код принципиально ущербен — тогда посоветуйте правильную структуру.
Преполагается, что объектов MyObject будет создаваться много.

P. S. По форуму искал, да всё что-то не то smile

Спасибо.

Добавлено @ 17:20 
var obj = new MyObject("inp", "obj"); не предлагать smile

Автор: vasac 28.8.2006, 17:49
Код

 GoDots : function() {
        this.input.value += "-";
        var t = this;
        setTimeout( ( function() { return t.GoDots(); } ), 200); // GOOD!
    },

Автор: Sardar 28.8.2006, 18:07
Можно и так:

Код
<html>
<head>
<title>test</title>
</head>
<body>
<script type="text/javascript">
function MyObject(obj) {
    if(!obj.tagName) //if !(obj instanceof HTMLElement) - долбанный ИЕ не знает о DOM'овских интерфейсах
        obj = document.getElementById(obj);
    var tmr = null;

    function godots() {obj.value += "-";}

    return {
        GoDots: godots, 
        Start: function() {
            tmr = setInterval(godots, 200);
        },
        Stop: function() {
            if(tmr) clearTimeout(tmr);
            tmr = null;
        }
    };
}

</script>
<div>
    <input type="text" size="50" id="inp" />
    <button onclick="obj.Start()">Start</button>
    <button onclick="obj.Stop()">Stop</button>
</div>
<script type="text/javascript">
    var obj = MyObject("inp");
</script>
</body>
</html>

Автор: dm9 29.8.2006, 10:29
vasac, большое спасибо, это работает. Пробовал вчера много способов, и был близок, но немного не дошёл. Теперь осознания языка чтало чуть больше smile

Sardar, в таком случае тебе вопрос smile
Однажды http://forum.vingrad.ru/index.php?showtopic=88463&view=findpost&p=680196.
Собственно, проникнувшись идеей smile я и решил вынести код в прототип, оставив в конструкторе только инициализацию — почему и возник вопрос данной темы.
Когда я писал выше: «Преполагается, что объектов MyObject будет создаваться много», — я намекал на то, что хочу сократить потребление памяти. Действительно ли это имеет смысл? Конечно, это вопрос не про мелкий скрипт, а про более серьёзную систему — скажем, а ля gmail.com, который может работать без перезагрузки страницы часами. Ну и просто по красоте кода и идеологии JavaScript — как правильнее?

Память памятью, но лично мне не нравится определение списка функций хэшем, через запятую — как-то неестественно. Просто я не привык? smile



Автор: Sardar 29.8.2006, 11:46
Цитата(dm9 @  29.8.2006,  09:29 Найти цитируемый пост)
— как правильнее?

Всё зависит от реализации JS. Например мозилла на каждый function() {} не "генерит код по новой", а создаёт новый контекст - обьект, который будет нормально удалён сборщиком мусора если на него не осталось ссылок. С другой стороны если взять IE, то он так долго может не протянуть. Проблема в утечке памяти, стоит любому JS обьекту связаться ссылкой с DOM (или любым ActiveX как XMLHttpRequest), то после перезагрузки такой обьект продолжает висеть в памяти и не убираеться пока браузер не закрыть. Если сам обьект ссылаеться на массу других обьектов, в данном случае на массу собственных функций-методов (или контекстов, называй как хочешь), то на лицо утечка памяти, серьёзная утечка.

Если помнишь меню в FAQ'e, что я делал, там все ноды раньше создавались сразу после загрузки. С каждой перезагрузкой пауза увеличивалась на 2-3 секунды, памяти по моему с 4-7Мб отьедалось. И так всё висело пока ИЕ не закрыть.

Резюмирую: если проект исключительно под ИЕ и должен работать стабильно - выноси всё из конструктора в прототипы, а события связывай через вызов временной анонимной функции (хак, но работает) или через attachEvent. Если тебя претит сама мысль таких ограничений и проект больше под хорошие браузеры - пиши как хочешь smile 
Интересно пофиксят ли это баг с утечкой памяти (ещё со времён ИЕ5.0) в ИЕ7.0...


Автор: dm9 29.8.2006, 12:08
Сардар, большое спасибо за разъяснения.

Для тех, кто ещё зайдёт: чтобы чуть лучше понять то, о чём сказал Сардар, можно глянуть статью http://htmlcoder.visions.ru/JavaScript/?29.
Там по ссылкам ещё есть статьи, но на английском. Попозже тоже посмотрю.

Автор: Alx 30.3.2007, 13:04
Цитата(vasac @  28.8.2006,  17:49 Найти цитируемый пост)
        setTimeout( ( function() { return t.GoDots(); } ), 200); // GOOD!

а зачем return? у меня и без него работает

Цитата(vasac @  28.8.2006,  17:49 Найти цитируемый пост)
        var t = this;

а не имеет ли в таком случае смысл объявить эту переменную первой строкой в описании класса и далее везде писать t вместо this?

Автор: Sardar 30.3.2007, 21:51
Цитата(Alx @  30.3.2007,  12:04 Найти цитируемый пост)
а зачем return? у меня и без него работает

Просто так smile

Цитата(Alx @  30.3.2007,  12:04 Найти цитируемый пост)
а не имеет ли в таком случае смысл объявить эту переменную первой строкой в описании класса и далее везде писать t вместо this? 

Нет, тут идея совсем другая. В основном форуме много размышлений на эту тему, ищи по ключевым "prototype this".

Автор: giologi 31.7.2007, 00:15
Люди Help... Вот попытался сделать анимацию изображения, у меня ничего не выходит...
Вот код...
Код

var step = 0;
function sizeq(t, s)
{
    if (s == 1)
    {
        setTimeout("anim()",1);
    }
    else if (s == 0)
    {
        t.style.height = '32';
        t.style.width = '32';
    }
}

function anim()
{
    step++;
    if (step == 8)
    {
        step = 1;
    }
    if (step == 1)
    {
        t.style.height = '34';
        t.style.width = '34';
    }
    if (step == 2)
    {
        t.style.height = '38';
        t.style.width = '38';
    }
    if (step == 3)
    {
        t.style.height = '40';
        t.style.width = '40';
    }
    if (step == 4)
    {
        t.style.height = '42';
        t.style.width = '42';
    }
    if (step == 5)
    {
        t.style.height = '44';
        t.style.width = '44';
    }
    if (step == 6)
    {
        t.style.height = '44';
        t.style.width = '44';
    }
    if (step == 6)
    {
        t.style.height = '46';
        t.style.width = '46';
    }
    if (step == 7)
    {
        t.style.height = '48';
        t.style.width = '48';
    }
    setTimeout("anim()",200);
}

Код

<img src="img/hormenu/1.png" border="0" width="32" height="32" onMouseOver="sizeq(this, 1);" onMouseOut="sizeq(this, 0);" />

Ращитано что сама функция anim() будет анимировать элемент, но либо она не вызиваеться либо я чегото не дописал или просто где-то ошыбка... Т.е. сам задум был чтоб это элемент не только анимировался а и еще плавно анимировался... ПОМОГИТЕ ПОЖАЛУЙСТА... Я в джава скрипте новичек...

Автор: Zeroglif 31.7.2007, 01:01
giologi, 

не трогая твою логику, наведу на кое-что:

- функция anim не видит t (для простоты/тренировки сделай t глобальной переменной);
- к цифрам, которые размеры, добавь px;
- отводя мышь, ты возвращаешь пикчеру размер, но setTimeout-то продолжает работать, нужно использовать clearTimeout;
- там же надо сбить step на ноль, чтобы анимация всегда начиналась с корректной точки;

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)