On Oct 6, 10:55 am, Thomas 'PointedEars' Lahn <PointedE...@web.de>
wrote:
> David Golightly wrote:
> > [...] Thomas 'PointedEars' Lahn [...] wrote:
> >> David Golightly wrote:
> >>> On Oct 4, 8:42 am, Defacta <vincent.margue...@gmail.com> wrote:
> >>>> setInterval(function(){fadePic();},50)
> >>> More concisely, without the closure:
>
> I don't think there is a closure here: `fadePic' is not resolved before
> the function argument is called. Not every function expression creates
> a closure.
>
> http://en.wikipedia.org/wiki/Closure...ter_science%29
According to the Wikipedia article, "a closure is a function that is
evaluated in an environment containing one or more bound variables.
When called, the function can access these variables." In this
instance, the anonymous function being passed to window.setTimeout as:
function doStuff() {
var o = {};
window.setTimeout(function () { fadePic(); }, 50);
}
has access to the variable "o" which is local to the containing
function "doStuff", hence, a closure. However, in the OP's example
(which is itself presumably wrapped in a function he neglected to
copy, or should be), none of those variables are used, except
"fadePic" itself. Since a closure is not needed here, I recommend not
using it; fadePic is itself a function that is not a property of any
object but the Global object, so the value of "this" is unchanged,
regardless of whether it is called within an anonymous function or
called directly.
>
> >>> window.setInterval(fadePic, 50);
> >> Which can change the meaning of `this' within `fadePic' significantly.
>
> >> Obviously you have little to no clue what you are talking about.
>
> > How does that work, exactly?
>
> Why, you could simply test it.
>
> `this' in a method refers to the calling object.
>
> I was referring to `fadePic' as an example, hence the "can". It will
> probably not change anything here because `fadePic' is probably called
> as a method of the same object in the scope chain.
In this example, we can drop the word "probably". Since "fadePic" is
not being called as a property of a local object, its "this" value
points to the Global object anyway.
>
> But if you use for example
>
> var o = {
> fadePic: function()
> {
> window.alert(this);
> }
> };
>
> // and then
>
> window.setTimeout(o.fadePic, 50) // [1]
>
> // instead of
>
> window.setTimeout(function() { o.fadePic(); }, 50)
>
> that changes the meaning of `this' in the method o.fadePic is a reference
> to. In the former case it would probably refer to the object setTimeout()
> is called as a method of; in the latter case it would refer to the same
> object as `o'.
>
> My point being was/is that these two approaches are not generally
> equivalent, and that avoiding (supposed) closures is not always the best
> approach.
That's a valid distinction, but understanding it is central to
effective JavaScript. What's necessary in the latter case -
preserving the object "o" within the scope chain, so that its property
"fadePic" may be called at a later time - is not necessary in the
former case. However, the latter example brings problems of its own,
as I've seen lots of beginners try:
function Foo() {}
Foo.prototype.doBar = function () { /* stuff here */ };
Foo.prototype.delayedBar = function () { window.setTimeout(function ()
{ this.doBar() }, 50); };
var foo = new Foo();
foo.delayedBar();
which gives a syntax error, since the Global object has no method
"doBar". Likewise,
Foo.prototype.delayedBar = function () { window.setTimeout(this.doBar,
50); };
will pass in a function, but as you say, its "this" will refer to the
Global object, not the object that inherits from Foo.prototype. The
(most likely) intended behavior, not immediately obvious to beginners,
is:
Foo.prototype.delayedBar = function () { var foo = this;
window.setTimeout(function () { foo.doBar() }, 50); };
I would, in general, discourage use of closures unless they're needed
for a specific, premeditated purpose; a recurring setInterval call
will preserve the scoped local variables in memory long after the
original function has returned and there is no longer a need for
them. When they are needed, it's a good idea to attempt to limit the
scope to prevent or at least minimize unintended memory leaks.
To sum up, it seems the best rule of thumb is to simply learn the
rules, and decide which technique to use based on what's needed in a
particular context.
-David