#javascript
#javascript
Вопрос:
В приведенном ниже коде javascript я хотел, чтобы элемент el указывал на div с идентификатором «divNavyBox». Вот код для divNavyBox:
<div id="divNavyBox" class="box" onmouseover="animated.doAnimation()"></div>
Приведенный ниже код является используемым javascript. Обратите внимание, что появляется предупреждение с информацией о типе el.
var animated = {
el : document.getElementById("divNavyBox"),
doAnimation : function() {
alert(typeof el);
if (el.className=="box") {
alert("2");
el.className="boxAlt";
}
if (el.className=="boxAlt") {
el.className="box";
}
}
};
Каждый раз, когда появляется предупреждение, в нем говорится, что el не определен. Почему он не определен, когда я объявляю его в начале кода и присваиваю ему элемент?
Ответ №1:
Вы ссылаетесь на el
, как будто это глобальная переменная. Вам нужно сказать this.el
Комментарии:
1. Пол, твой ответ работает, только если функция вызывается особым, странным способом. Если это так
animated.el.onclick = function() {animated.doAnimation()};
, то вы правы. Однако, в более распространенном и, вероятно, более практичном случаеanimated.el.onclick = animated.doAnimation
внутриdoAnimation
функцииthis
будет ссылаться на элемент DOM, а не наanimated
объект, что делаетthis.el
неопределенным.
Ответ №2:
Объекты не имеют области видимости, только функции. Вы ожидаете el
разыменования из объекта, но когда функция фактически выполняется, ей не на что el
ссылаться: локальной переменной функции el
не было присвоено никакого значения, и глобальной переменной el
также нет. Если бы вы хотели использовать just el
в своей функции, вы бы сделали внешний контейнер функцией и изменили el
его на локальную переменную, или сделали el
глобальной, или ссылались на animated.el
.
Однако, поскольку функция ссылается только на один элемент, зачем вообще давать функции имя? Почему он не привязан к событию divNavyBox
? Пожалуйста, объясните, как вы вызываете функцию и / или привязываете ее к событию, чтобы мы могли внести в это больше ясности.
Есть еще одна проблема: важно вообще не закрывать элементы DOM или сохранять ссылки на них где-либо в вашем скрипте, поскольку это может привести к утечкам памяти. Это означает, что вы не только должны использовать this
для ссылки на выбранный div внутри функции, вы также должны полностью исключить el
переменную, чтобы не было ссылки на элемент. Вот как я бы это сделал:
document.getElementById("divNavyBox").onclick = function() {
alert(typeof this);
if (this.className === "box") {
alert("2");
this.className = "boxAlt";
} else if (this.className === "boxAlt") {
this.className = "box";
}
// or alternately, removing the alerts, the whole function could be:
this.className = this.className === 'box' ? 'boxAlt' : 'box';
};
Ключевое слово this
всегда ссылается на специальный объект, который соединяется с каждой функцией javascript при ее запуске. В случае событий в элементах DOM, this
будет ссылаться на сам элемент. Важно помнить о том, this
что он всегда будет динамически определяться во время выполнения функции и никогда не будет иметь значения во время объявления функции.
Просто для наглядности, вот как могла бы выглядеть функция, если бы вы сделали это через закрытие:
(функция() { var el = document.getElementById(«divNavyBox») el.onclick = функция() { el.className = el.className === ‘box’ ? ‘boxAlt’: ‘box’; }; }());
Как я уже сказал, это создаст замыкание над внешней анонимной функцией, сохраняя el
созданный экземпляр и удерживая ссылку на div. Поскольку сам div имеет обратную ссылку на внутреннюю функцию (которая сама по себе поддерживает закрытие открытым), у браузеров может возникнуть проблема с разрешением этого цикла. Это связано с разделением между DOM-объектами браузера, обрабатываемыми в движке браузера, и объектами javascript, обрабатываемыми в отдельном движке javascript, что не позволяет ни одному из них обнаружить, что ссылка является циклической и объекты могут быть собраны в мусор. (Возможно, некоторые браузеры решили эту проблему, но не все из них, и я точно знаю, что по крайней мере у IE6 есть проблема с этим).
Если у вас есть дополнительные замечания о том, почему функция event должна иметь имя или ссылаться на другое место, пожалуйста, прокомментируйте, и я соответствующим образом обновлю.
Комментарии:
1. @Michael Пожалуйста, обратите внимание, что я обновил свой ответ, и есть некоторые моменты, которые вы, возможно, захотите рассмотреть.
Ответ №3:
Выполните одно из следующих действий, чтобы правильно ссылаться на el:
alert(typeof this.el);
alert(typeof animated.el);
Комментарии:
1. Кон, твой ответ № 1 работает, только если функция вызывается особым, странным способом. Если это так
animated.el.onclick = function() {animated.doAnimation()};
, то вы правы. Однако, в более распространенном и, вероятно, более практичном случаеanimated.el.onclick = animated.doAnimation
внутриdoAnimation
функцииthis
будет ссылаться на элемент DOM, а не наanimated
объект, что делаетthis.el
неопределенным. Кроме того, # 2 будет работать, но ни один из ваших пунктов не касается создаваемого ненужного замыкания.