7 ms·
An Introduction to JavaScript's "this"
- mhansen 17y agoThe way I remember it: this is whatever is before the dot when you call the function. 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'.
- judofyr 17y agoIs this supposed to be Ruby? class HotDog: condiments def getCondiments return @condiments // @ is a reference to the current instance of HotDog. end end
- jmtulloss 17y agosorry, that was typed up pretty quickly, and I'm not a rubyist... care to correct it?
- jhancock 17y agoclass 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.
- xtho 17y agoNo, 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 end
- jhancock 17y agooops, sorry. yes, the first line would define a "class instance" variable. btw, I didn't show the attr_accessor meta-programming sine it hides the guts of the excercise.
- jmtulloss 17y agoI made some corrections. How's it look now?
- jhancock 17y agoI posted a bit too quick and too late at night. See corrections on this thread.
- Bluem00 17y agoThis article does a good job of explaining a concept I had trouble with when first using javascript. Now, I usually use the approach recommended in the article of setting a private variable (e.g. self, or my) to the current value of 'this' in a javascript class. 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.
- aboodman 17y agoThere is indeed a preference for window (really the global) object. Try these: <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.
- aboodman 17y agoBTW, imo, the behavior of |this| is a really unfortunate design flaw of JS. The amount of time that must have been spent learning and teaching this edge case over and over to every person new to the language is ... well, it's big.
- trjordan 17y agoDoes anybody have a mirror? It appears to be down for me.
- _ck_ 17y agohttp://addons.mozilla.org/en-US/firefox/addon/2570 http://addons.mozilla.org/en-US/firefox/addon/2570 oh and http://google.com/search?q=cache:http%3A%2F%2Fjustin.harmonize.fm%2Findex.php%2F2009%2F09%2Fan-introduction-to-javascripts-this%2F http://google.com/search?q=cache:http%3A%2F%2Fjustin.harmoni...
- kwamenum86 17y agoThe function: setTimeout(30, function() { myHotDog.getCondiments.apply(myHotDog); }); can actually just be: setTimeout(30, function() { myHotDog.getCondiments(); }); apply is definitely useful but it just makes the code more verbose in this case.
- nixy 17y agoWhich JS engine allows you to call setTimeout like that? Isn't setTimeout(expression, timeInMs [, args]) the right way to go?
- bouncingsoul 17y agoThat's correct, but the optional args parameter isn't supported in IE. So if you want to use setTimeout or setInterval to call a function with arguments you have to do it as an anonymous function with your function call inside. You're right though that milliseconds should be the second argument, not the first. https://developer.mozilla.org/En/Window.setTimeout https://developer.mozilla.org/En/Window.setTimeout
- kwamenum86 17y agoYes my mistake. milliseconds is the first argument. I just copied the function text verbatim. My real point was that you don't need to use apply in this context,, as the author implied.
- axod 17y agoIt's not a quirk, it doesn't need "fixing". Get a good javascript book. Still surprising how many people try to learn js by feeling around in the dark or by googling.
- jmtulloss 17y agoI absolutely agree. I tried to put "fixing" in quotes as much as possible. However, you have to see that for many programmers, it is unexpected behavior. In the eyes of many UI specialists, unexpected behavior is the definition of a quirk. JS fanatics have to be accepting of the fact that JS is not a regular language that follows "regular" rules.
- axod 17y agoSure, I agree... And if you go in #javascript on freenode for a few minutes, you'll see endless questions about why their event handler doesn't work. Endless answers "use a closure". I just wish people would read a book on the language first, then the behavior would be pretty obvious and expected.
- volida 17y agoThis article is wrong. You need to use prototype when defining your functions. 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>
- Bluem00 17y agoWhile you can use prototype, why do you need to? What specifically do you mean by "the article is wrong?"
- volida 17y agoif you dont use prototype the function will not belong το the new object you create, therefore you will not be able το call the function from settimeout, which was the problem the author assumed το have.
- DougBTX 17y agoTry extending the time on your timeout in the example, say to 30000 milliseconds. You might get a surprise when you see your function get called immediatley. 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.
- deleted 17y ago[deleted]
- volida 17y agoSorry, I was typing a bit fast. This should be ok. window.onload= function() { setTimeout( "myHotDog.getCondiments();", 3000); };
- diN0bot 17y agoone neat way to define a class is like so: 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() { ... }, ... });