views:

98

answers:

4

I find this behavior of the global window object a little weird.

var x = 10;
function SomeClass(){
    var y = 15;
    console.log("Someclass:y - " + this.y); //prints undefined
}

console.log("window.x: " + window.x);   //prints 10

var obj = new SomeClass();
console.log("obj.y: " + obj.y); //prints - undefined

Both variables x and y are local (to window and to SomeClass respectively). Despite calling y from an object context, it only prints undefined - presumably because that is how local variables are supposed to behave. But window.x behaves differently by printing value of x. I understand that this is how you create global varibles but is this a special property of window that makes local variables behave like object variables?

+2  A: 

in order to achieve what you are trying to with var y, it should be this.y = 15; That will allow you to reference it via this.y but also obj.y The reason it is printing undefined is simply because y is not assigned to be a member of SomeClass, just as a random variable within it.

http://www.javascriptkit.com/javatutors/object.shtml

Angelo R.
+2  A: 

you need to define y as a member of SomeClass. Otherwise it's just a local private variable within the closure of function SomeClass, but not a publicly accessible member of a SomeClass object, so:

function SomeClass(){
    this.y = 15;
    console.log("Someclass:y - " + this.y); //prints 15
}

Good question though about a variable assigned to the global space also being an attribute of window, not sure about that one. One would think you would need

this.x="something"

in order to access it through window.x

brad
The top half of your answer is good :)
sje397
Thanks. The second part of your answer is exactly my question. 'x' seems to behave like a class variable of window, although it is just defined like a local varable.
Ara
ya that's an interesting thing to note that var x is the same as window.x in the global scope but var x is not the same as this.x in the functional scope
brad
+4  A: 

According to the ECMAScript language specification:

If the variable statement occurs inside a FunctionDeclaration, the variables are defined with function-local scope in that function, [...]. Otherwise, they are defined with global scope (that is, they are created as members of the global object [...])

Essentially this means the var keyword has a slightly different meaning inside a function and in the global scope.

I think one way to look at it is that creating a variable in global scope is more like setting an instance variable on an object after it is created than like setting a local variable.

Compare setting a local variable in the constructor:

function SomeClass(){ 
    var y = 15; 
} 

var obj = new SomeClass(); 
console.log("obj.y: " + obj.y); //prints - undefined 

and setting a instance variable after the object is created:

function SomeClass(){ 
} 

var obj = new SomeClass(); 
obj.y = 15;
console.log("obj.y: " + obj.y); //prints - 15
Mario Menger
True. So can I say that var x= 10 is equivalent to saying window.x = 10? A special behavior of code that is outside?
Ara
Yes, in global scope where window is the global object.
Mario Menger
The answer that I was looking for. Thanks Mario!
Ara
+1 For referencing the specification and actually answering the question.
CalebD
+1  A: 

Hi Ara,

The key point to take away is that in your class example, y is private.

As the others have mentioned there are a few ways you can make it a public member variable, but the point I wanted to mention is that the fact that the following structure:

function SomeClass(){
  var y = 15;
}

...can be used to your advantage since it is private.

Typically I use a couple of different patterns for creating classes and objects this but one neat thing you can do is return an object literal from your function that has functions embedded in it that can reference y, while not exposing y to the outside world.

Pop this example into a page and try it out and see that you can read from and write to y using accessor methods:

<script type="text/javascript">
function SomeClass() {
  var y = 15;
  return {
    getY : function() { return y },
    setY : function(newY) { y = newY; }
  };
};

var obj = new SomeClass();

function showY() {
    alert("obj.getY: " + obj.getY()); // alerts current value of y.
}

function updateY() {    
    obj.setY(25);
    alert("updated.");
}

</script>
<input type="button" onclick="showY();return false;" value="showY"/>
<input type="button" onclick="updateY();return false" value="updateY"/>

Then click on "showY" first, then "updateY", then "showY" again to see the behavior.

This isn't the only pattern I personally use, but javascript is so flexible there's a lot of fun things you can do with it.

Hope I didn't blast you too much with that, and hope it helps a little bit with the concepts!

InteractiveLogic