views:

115

answers:

5

In the following code:

    <script type="text/javascript">

        var i = 10;

        function Circle(radius) {
            this.r = radius;
            this.i = radius;
        }

        Circle.i = 123;

        Circle.prototype.area = function() { alert(i); }

        var c = new Circle(1);
        var a = c.area();

    </script>

What is being alerted? The answer is at the end of this question.

I found that the i in the alert call either refers to any local (if any), or the global variable. There is no way that it can be the instance variable or the class variable even when there is no local and no global defined. To refer to the instance variable i, we need this.i, and to the class variable i, we need Circle.i. Is this actually true for almost all Object oriented programming languages? Any exception? Are there cases that when there is no local and no global, it will look up the instance variable and then the class variable scope? (or in this case, are those called scope?)

the answer is: 10 is being alerted.

A: 

What you are seeing is a closure.

http://www.jibbering.com/faq/faq_notes/closures.html

If you want this.i or Circle.i, you must explicitly refer to them.

Just like in Python (self.x and cls.x), Javascript has no syntactic sugar for instance or class/prototype attributes.

Marco Mariani
it is a closure? there is no function being created together with a scope chain. i thought a closure always is a function together with a scope chain?
動靜能量
Where's the closure here?
J-P
oh sorry, it's still in my coffee :-)
Marco Mariani
wait a second... on second thought, the line "Circle.prototype.area = function() { alert(i); }" actually assigns a function reference to the left hand side, so, a function is created, with a scope chain containing the global scope. So in fact a closure is created. Just that the scope chain has no local scope since no function is invoked, so no new scope is added.
動靜能量
A: 

in general object oriented programming language, instance variable (as the name indicates) can be accessed only through the instance of a class(except static variables which can be accessed by class name). So when ever you want to refer an instance variable you need to have the object(instance) of the class.

biluriuday
i am talking about accessing instance variable outside the class, not within the class. sorry, forgot to mention it
biluriuday
A: 

To refer to an instance variable you must use this.i. Circle.i refers to a static property on the Circle constructor -- it will have no affect on instances of Circle.

J-P
A: 

No that is not true.

Most languages will let you access instance variables without using something like this.i to specify that it's an instance variable.

Languages that really are object oriented, like Java, C# and VB (7+), doesn't even have any global variables at all.

Javascript isn't really an object orented language, it's a procedural language with limited support for object orientation. As it doesn't have classes, there isn't any class scope, so you need to use the this keyword to specify the object scope.

Guffa
Javascript is a terrific object oriented language! It's just not a *class based* objected oriented language. :)
deceze
Javascript uses prototypes instead of classic classes. So while it cannot be called object oriented in Java/C++ sense, calling it procedural with limited object support isn't right.
ymv
Quoting Doug Crockford "JavaScript is class free. It uses prototypes. [...] Java is not powerful enough that you can write in a JavaScript style in Java; it’s just not good enough. JavaScript is, so you can do it the other way around, because it’s the more powerful of the models."http://developer.yahoo.com/yui/theater/video.php?v=crockonjs-2
Colonel Sponsz
@deceze: Just because it supports object orientation doesn't make it an object oriented language. You can do object oriented programming in any language, even if it doesn't support it. I have even done some in assembler...
Guffa
@ymv: What isn't right about it? The support for object orientation is really limited in Javascript. There is for example no inheritance, which is one of corner stones in OOP.
Guffa
@Colonel: The fact that Java is not good at being Javascript doesn't really say anything about either language other than that they are different. Java also sucks at being Assembler, FORTRAN, Lisp, PROLOG and a lot of other languages...
Guffa
@Guffa More from that same Crockford Talk "[JavaScript] is all about objects; it’s an object oriented language. I’ll try to demonstrate to you that it is more object oriented than Java. For a long time, a lot of the opinion about this language was that it’s not object oriented, it’s object based, it’s deficient. It turns out it’s actually a superior language.In this language, an object is a dynamic collection of properties. This is quite different than in most of the other object oriented languages in which an object is an instance of a class,..."
Colonel Sponsz
There *is* inheritance, **prototypical inheritance**. Javascript is 100% object oriented. It just doesn't have *classes*, which is *not* required to be OO.
deceze
@Guffa Classical Inheritance in JavaScript: http://www.crockford.com/javascript/inheritance.html
Colonel Sponsz
@deceze: Yes, you can simulate inheritance by copying objects. Can you simulate encapsulation too?
Guffa
@Guffa Encapsulation can be done with closures: http://www.jibbering.com/faq/faq_notes/closures.html#clEncap
Colonel Sponsz
IMHO a better demonstration of encapsulation: http://javascript.crockford.com/private.html
deceze
`"you can simulate inheritance..."` - An object can either inherit or it can't, "simulating" it is nonsense. Classes are just one way to do it. Javascript *has* inheritance, it just isn't your classical class style inheritance. So, Javascript has objects, inheritance and public and private properties and methods. Why doesn't that qualify as OO? Actually, class based OO languages require a two step process to work with objects: definition and instantiation. That's arguably rather procedural. Javascript lets you work with objects right from the start. Isn't that even more OO?
deceze
+1  A: 

Behold:

var i = 10;

function Circle(radius) {
            var i = radius || 0;
            this.r = i;
            this.i = radius;
            this.toString = function(){ return i; };
        }    
var nwCircle = new Circle(45);

alert(nwCircle.r); //=>45;
alert(nwCircle); //=>45 (toString found local i);
alert(i); //=>10

Now, in the Circle constructor you created a closure to the (local, belonging to the object itself) variable i. The globally defined i is unaffected. So, in javascript it depends on where you define your variable. In javascript at least, a bottom up search (from the local scope to the global scope) is done for i and the first one found is used. So if the Circle constructor didn't contain a variable called i, the global i would be used.

KooiInc