Path: archiver1.google.com!news1.google.com!newsfeed.stanford.edu!news-spur1.maxwell.syr.edu!news.maxwell.syr.edu!newsfeed1.uni2.dk!newsfeed101.telia.com!nf02.dk.telia.net!news104.dk.telia.net!not-for-mail Sender: Lasse R. Nielsen@SUZIE Newsgroups: comp.lang.javascript Subject: Re: Using setInterval inside an object References: <3f004263$0$76159$edfadb0f@dread11.news.tele.dk> <3f005408$0$76130$edfadb0f@dread11.news.tele.dk> <290e65a0.0306302017.b46bce8@posting.google.com> <3f0145b5$0$97265$edfadb0f@dread12.news.tele.dk> <3f017100$0$97169$edfadb0f@dread12.news.tele.dk> <3f019b7d$0$97230$edfadb0f@dread12.news.tele.dk> <3f02b635$0$97201$edfadb0f@dread12.news.tele.dk> <3f044c3c$0$97223$edfadb0f@dread12.news.tele.dk> <3f046e20$0$97218$edfadb0f@dread12.news.tele.dk> From: Lasse Reichstein Nielsen Date: 03 Jul 2003 23:55:28 +0200 Message-ID: User-Agent: Gnus/5.0808 (Gnus v5.8.8) XEmacs/21.4 (Native Windows TTY Support (Windows)) MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Lines: 197 NNTP-Posting-Host: 62.107.35.50 X-Trace: 1057269112 news.stofanet.dk 1651 62.107.35.50 X-Complaints-To: Telia Stofa Abuse "Daniel" writes: > GREAT way to put it! Actually, I think of the parentheses like this: > > var anObject = (function(){...})(); > > with (function(){...}) being evaluated first, then the return value of that > being evaluated by (); then the return value of that being assigned to > anObject. Here you are using confuzing terminology (saying "return value" twice even though there is only one function call). I'll try to be very precise: "function (){...}" is a function *expression* (a sequence of characters that match a production of the grammar called "function expression"). It is an expression (rather than, e.g., a statement), so it can be evaluated to a value. That value is a function *value* (you say "return value", but there is nothing being returned yet, the body of the function is not evaluated at this point). Functions in Javascript are objects which have an internal method called "[[Call]]". "(function(){...})()" is again an expression, in this case a function application. It consists of two parts, the *expression* before the parentheses, which should (if the program is correct) evaluate to a function *value*, and the argument expressions og which there are zero in this case. To evaluate a function application, first evaluate the expression in the function-position. In this case it is a function expression, so it directly evaluates to an (anonymous) function value. Then evaluate the arguments, in this case it is trivial. Finally, call the function with the arguments. At this point, the body of the function is evaluated. The reteurn value of *that* is the value of the application expression. "var anObject = function(){...}();" is not an expression, it is a statement. More precisely, it is a "variable declaration and initalization" statement. The Javascript interpreter already noticed that "anObject" was declared as a local variable, it checks that before executing anything, so the scope of the variable can precede its declaration. To find the effect of a statement, it is executed (not evaluated, as it doesn't have to have a value). To execute an assignment (what an initialization statement really is), you first evaluate the right-hand side expression. In this case, it is the return value of calling the anonymous function. Then, and only then, is the "anObject" variable bound to that value. Until this, it has been undefined. That value, the return value of the call to the anonymous function (which we have no reference to otherwise[1], so it will never be called again) just happens to be a function itself, a completely different function. > But that's not entirely true, because at the point of assigning anObject a > value, which, as I understand, is what is happening here, I don't see any > evaluation being made just yet, at that point I see it as you put it, that > is: > > var anObject = (function(){...}();) > > in the sense that at this particular instant in time, anObject holds a > reference to all definitions inside these parentheses, and these definitions > will stay "untouched" or "unexecuted" or "unevaluated" or "unprocessed" ;) > until anObject is called in another context. Not so. The parentheses (they are curved, not squiggly) are only grouping. They don't delay the execution. Javascript is a strict language, so you don't pass around unevaluated code just like that. > I'm glad you write this, because that's actually exactly what I mean =) (See > why I say you're better at English than I am? ;) Years of practice writing academic English will do that to you. I can talk for hours about closures, but I have little to no knowledge of the names of kitchen utensils :) > > 2.3 : assign the result of 2.2 to the new global variable "constructor". > > Global? I thought it'd be a private member of oneOff? The constructor variable has not been declared local by a "var constructor" declaration. Therefore it defaults to being global. > > 2.4 : return the value of the global variable "constructor". This is the > > result of 2. > > 3 : assign the result of 2 to the local variable "oneOff". > > 4 : use the value of the variable "oneOff" as a constructor with > > no arguments (new ...()). That is, create a new object and > > call the function with "this" pointing to the new object. > > 4.1 : execute document.write(" 2") > > This is executed as a result of the instantiation of the constructor object, > right? Not Mr. One-Off? The value of the variable "oneOff" is a function. That function's body contains 'document.write(" 2")'. When writing "new oneOff()" you use that function as a constructor, but that includes calling it as a function. The "document.write" is executed as part of the expression "new oneOff()". > > That is much closer to Javascript than most languages then. Javascript > > is a prototype based (as oppesed to class based) object oriented language. > > That's what I thought, since they're both ECMA-based, but when I see "class" > being used, I suddenly start wondering... I do that a lot... You can emulate classes in Javascript, and people sometimes refer to elements created using the built in constructors (e.g., Array) as "instances of the class Array". It is, however, people used to class based languages that are trying to hammer in a screw. Needless detail on how objects are created: Objects are, obviously, an important datatype for Javascript. As I said earlier, functions are objects with some extra functionality, and so are Regular Expressions and a lot of other utility objects. All objects have a property called "constructor". It refers to the function that was (or could have been) used as a constructor to create the object. If you write "var x={};" then "x" refers to a new, (almost) empty object. The constructor for it is the one called "Object". The constructor of an array is "Array", and so on. Each function can be used as a constructor and therefore has a property (remember, they are objects too) called "prototype". When you look for a property of an object, it first checks if the object has had that property assigned to it. If not, it checks if it is a property of its prototype, and if not, it continues down the prototype chain (I haven't checked where it ends, but probably at Object.prototype). Quiz: What does the following do? --- var x = new Object(); Object.prototype.foo = 42; alert(x.foo); --- When you call a function as a method of an object, the "this" keyword will refer to that object. That is: --- var x = new Object(); x.foo = function () {return this;}; alert(x == x.foo()); --- will alert "true". It is the "." notation (or the equivalent []-notation) that marks a function call as a method invocation. If you changed the above to: --- var x = new Object(); x.foo = function () {return this;}; var bar = x.foo; alert(x == bar()); --- it alerts "false", even though "x.foo" and "bar" both refer to the exact same function object. It is the way the function is called that sets the "this" keyword's value. When you call a function directly, and not as part of an object, then the "this" keyword refers to the global object, where the global variables live. Since there are no classes in Javascript, the term "constructor" might also be a little misleading. As I said, any function can be used as a constructor. What happens when you write new foo(42); is that you call the function "foo" with the argument "42". However, where a normal function call of that kind would have set the "this" reference to the global object, and a method invocation would set "this" to the object of the method, the "new" makes sure that the "this" keyword refers to an entirely new object. If the foo function doesn't return something (or if it returns something that is not an object), that new object is the value of the entire expression. If it returns another object, they object will be the value of the "new" expression. --- function foo(x) { this.n=x; } foo(37); /* sets this.n = 37 with this == global object */ var o1 = new Object(); o1.bar = foo; o1.bar(42); /* sets this.n = 42 with this == o1 */ var o2 = new foo(87); /* sets this.n = 87 with this == new object == o2 */ alert(n +","+ o1.n +","+ o2.n); /* alerts "37,42,87" */ --- /L -- Lasse Reichstein Nielsen - l...@hotpop.com Art D'HTML: 'Faith without judgement merely degrades the spirit divine.'