An Introduction to JavaScript's "this"
justin.harmonize.fm
justin.harmonize.fm
However, I think the article is slightly incorrect on one minor point. It states, "this wants to be window whenever possible, which is not always what you want." I believe the correct description is: the 'this' variable in a function called in response to an event on dom object is set to that dom object. For the example given in the article, this is set to the window object because setTimeout causes an event on window to fire, not because there's any inherent preference for the window object.
<script> alert(this == window); function foo() { alert(this == window); } foo(); </script>
|this| is basically a magical variable that by default is set to the global object, but can also be set by the caller of a function one of two ways:
a) by setting a reference to the function on an object, and calling it with object or bracket notation: var someObj = {}; someObj.f = theFunction; someObj.f(); // now |this| inside theFunction will // point to someObj someObj["f"](); // same thing
b) by using apply: theFunction.apply(someObj);
You are right that in the case of event handlers, it is common in the DOM for event handlers to get their |this| set to the DOM node that fired the event. Since the default value of |this| is the global object, it isn't possible in the case of setTimeout for us to tell whether the caller (the host) explicitly set it, or if the function is being called without any value set for |this|.
Basically, |this| is an extra parameter to any function. It is controlled by the caller, and as such, should either be documented as part of the signature of the function, or else should not be relied on by the implementation of the function.
The common misunderstanding with people new to JS is that they expect |this| to be controlled by the callee, like it is in lots of other popular languages, and are surprised when calling convention can change its value.
So if there is no obvious thing for this to point at, it'll point at the global object. Its just implementation detail that in browsers it points to the window object.
"new", I believe, is actually an ancient relic of the prototypal class system. That's another topic entirely, but it's incredibly cool. Check out Douglas Crockford's articles on inheritance if you want closure on the issue. He has written way more than I have on the topic.
I believe it is quite the opposite. It was a failed attempt to make the prototype-based object system look like class-based one. I vaguely remember reading this opinion in Crockford's "Javascript:The Good Parts" book.
E.g. for car.drive(); in the drive function, any reference to 'this' will get 'car'. If the function is called on it's own, as in 'drive()', 'this' will refer to the Global object (bad)
It's also possible to change 'this' by using the Function.prototype.apply() method, which allows you to pass a 'context' parameter that will become 'this'.
can actually just be: setTimeout(30, function() { myHotDog.getCondiments(); });
apply is definitely useful but it just makes the code more verbose in this case.
You're right though that milliseconds should be the second argument, not the first.
class HotDog:
condiments
def getCondiments
return @condiments // @ is a reference to the current instance of HotDog.
end
end class HotDog
@condiments
def getCondiments
return @condiments // @condiments is an instance variable of an instance of HotDog
end
end
note the mod to both the ivar def and the comment. You also do not need the initial ivar "definition" as ruby defines them on the fly when they are first referenced.The first @condiments would define a class variable.
class HotDog
attr_accessor :condiments
end
Or for Java-socialized folks: class HotDog
def initialize
@condiments = nil
end
def getCondiments
return @condiments
end
endbtw, I didn't show the attr_accessor meta-programming sine it hides the guts of the excercise.
I just wish people would read a book on the language first, then the behavior would be pretty obvious and expected.
function MyClass(a, b) {
// use this function as an instance constructor
// eg, var m = new MyClass('foo', 'bar');
this.a = a;
this.b = b;
}
MyClass.prototype = {};
_extend(MyClass.prototype, {
instanceMethod: function() {
...
},
...
});Here is how to do it:
<html>
<head>
<script>
function HotDog () {
this.name=arguments[0];
}
HotDog.prototype.name=null;
HotDog.prototype.getCondiments= function () {
document.getElementById('test').innerHTML='started...' +this.name;
};
var myHotDog = new HotDog('test 001');
window.onload= function() {
setTimeout(30, myHotDog.getCondiments());
};
</script>
</head>
<body>
<div id=test>loading...</div>
</body>
</html>In the article, you are right that he should use prototype, but not for the reason you mention. In the example, he does this.foo = function, so the function does get associated with the object. The problem is that the function gets recreated every time the HotDog constrictor gets called. Better to put getCondiments on the prototype, so that it is only defined once.
window.onload= function() {
setTimeout( "myHotDog.getCondiments();", 3000);
};Also, your code isn't right. You're calling myHotDog.getCondiments instead of passing a reference to setTimeout.