In the javascript code below, I wanted element el to point to a div with the ID "divNavyBox." Here is the code for divNavyBox:
<div id="divNavyBox" class="box" onmouseover="animated.doAnimation()"></div>
The code below is the javasc开发者_JAVA百科ript used. Notice that an alert pops up with information about the type of 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";
}
}
};
Every time the alert pops up, it says that el is undefined. Why is it undefined when I declare it in the beginning of the code and assign it an element?
You are referring to el
like it's a global variable. You need to say this.el
Objects do not have scope, only functions. You're expecting el
to be dereferenced from the object but when the function actually runs, there is no el
for it to refer to: The function local variable el
has not been set to any value, and there is no global variable el
either. If you wanted to use just el
in your function, you would make the outer container a function and change el
to be a local variable of it, or make el
global, or refer to animated.el
.
However, since the function only refers to a single element, why bother to give the function a name at all? Why isn't it bound to an event of divNavyBox
? Please explain how you're calling the function and/or binding it to an event so we can give you more clarity on that.
There's a further issue: it's important to not to make a closure over DOM elements at all or keep references to them anywhere in your script as this can lead to memory leaks. This means that not only should you use this
to refer to the clicked div inside the function, you also should eliminate the el
variable entirely so there is no reference to the element. Here's how I would do it:
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';
};
The keyword this
always refers to the special object that is paired with every javascript function when it runs. In the case of events on DOM elements, this
will refer to the element itself. The important thing to remember about this
is that it will always be dynamically determined at function running time and never has meaning during function declaration time.
Just for clarity, here's how the function might look if you DID do it via a closure:
(function() { var el = document.getElementById("divNavyBox") el.onclick = function() { el.className = el.className === 'box' ? 'boxAlt' : 'box'; }; }());
As I said this will create a closure over the outer anonymous function, keeping el
instantiated and holding a reference to the div. Since the div itself has a reference back to the inner function (which itself is the thing keeping the closure open), browsers can have a problem resolving this circular. This is due to the separation between the browser's DOM objects being handled in the browser engine and the javascript objects being handled in a separate javascript engine, preventing either one from detecting that the reference is circular and the objects can be garbage collected. (Some browsers may have solved this, but not all of them, and I know for a fact that at least IE6 has a problem with this).
If you have further notes on why the event function needs to be named or referenced elsewhere, please comment and I'll update accordingly.
Do one of the following to properly reference el:
alert(typeof this.el);
alert(typeof animated.el);
精彩评论