2

Variable scope in JS is confusing the hell out of me. In the following code, if I use the setClient public method to set a clientID I can then access the value from inside the track method using the getClient method. I cannot, however, access the value of the private member 'version' this way (or any other private member). I had assumed that var _this = this would create a closure of some sort allowing access to the scope of the Container function.

And now I'm confused. I realise this is probably really simple though, so I thought I'd ask here. Where on earth have a grasped the wrong end of the stick?

function Container()
{
 // private members
 var version = '0.1';
 var CID = false;
 var _this = this;
 
 // public members
 this.getVersion = function() { return _this.version; }
 this.getClient = function() { return _this.CID; }
 this.setClient = function(CID) { _this.CID = CID; }
 
 // private methods
 this.getQS = function() { return _this.version; }
 
 // public methods
 this.track = function()
 {
 if (_this.CID)
 {
 var date = new Date();
 
 data = 
 {
 cid: _this.getClient(),
 sw: screen.width ? screen.width : false,
 sh: screen.height ? screen.height : false,
 d: date.getTime()
 }
 
 qs = '';
 
 for (p in data) { qs += p+'~'+data[p]+'-'; }
 
 var elHd = document.getElementsByTagName("head")[0]; 
 var elScr = document.createElement('script');
 elScr.type = 'text/javascript';
 elScr.src = 'http://example.org/'+qs+
 'version-'+_this.getVersion();
 
 elHd.appendChild(elScr);
 }
 else
 {
 alert('no client ID');
 }
 }
}
Alex
1,6101 gold badge16 silver badges27 bronze badges
asked Mar 23, 2009 at 19:49

4 Answers 4

1

Cleand up your Container constructor a bit. The version and CID variables are private and within the Container constructor scope, so you do not need the this scope reference, and it would not work at all. this. reference would be needed for public accessible properties and methods, and extremely useful when you define the prototype outside of the constructor function, as shown in the second code block.

function Container() {
 var version = "0.1", CID = false;
 this.getVersion = function() { return version };
 this.getClient = function() { return CID };
 this.setClient = function(value) { CID = value };
 this.track = function() {
 if (CID) {
 var qs = "", data = {
 cid: this.getClient(),
 sw: screen.width ? screen.width: false,
 sh: screen.height ? screen.height: false,
 d: (new Date).getTime()
 };
 for (var p in data) qs += p +"~"+ data[p] +"-";
 var js = document.createElement("script");
 js.type = "text/javascript";
 js.src = "http://example.org/"+ qs +"version-"+ this.getVersion();
 document.getElementsByTagName("head")[0].appendChild(js);
 } else {
 alert("No Client ID");
 }
 };
};

this. reference becomes crucial when you are adding/overriding the prototype after the constructor.

function Container2() { }
Container2.prototype = {
 CID: null,
 version: "0.1",
 track: function() {
 alert(this.version);
 }
}
answered Mar 23, 2009 at 20:19
Sign up to request clarification or add additional context in comments.

2 Comments

Thank you very much. I was clearly labouring under the false impression that i needed to create a closure or back-reference of some kind. I think it's back to the o'reilly books for me
No problem, it takes a bit to wrap your head around it. And as mentioned in another post here, crockford.com/javascript/private.html is a great read to help solidify how it works.
0

I'm not sure I'm understanding where you are confused (or why you are doing things the way you are, so I may be meta-confused). What happens if you just do:

this.getVersion = function() { return version; }
answered Mar 23, 2009 at 19:58

Comments

0

The variable version is not a member field of the Container class. It is a local var that only exists for the duration of the Container constructor. You need to create it thus (as you are with the methods):

this.version = "0.1";

You should do the same for the CID field. Better yet, add them to the prototype object of your class.

answered Mar 23, 2009 at 20:08

Comments

0

The simple answer is to use

this.getVersion = function() { return version; }

Because the JavaScript functions are closures the reference to version, a local variable, in the function above can be accessed even after the function returns. Trying to access _this.version is an attempt to read the version member of the _this object. Since you never assigned _this a version member, it will return a value of undefined.

In JavaScript, you'll only be able to access members that are either explicitly added to the object you're working with, or added to that object's prototype, or the prototype's prototype, etc.

More info on using private members with JavaScript can be found in a great article by Douglas Crockford: Private Members in JavaScript

Alex
1,6101 gold badge16 silver badges27 bronze badges
answered Mar 23, 2009 at 21:17

Comments

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.