I'm trying to write an application in JavaScript, which I've been using for bits of scripting in web pages for years, and I find my understanding of scope and object orientation is coming up somewhat short. My background is mostly in object oriented languages like C# and Ruby so JavaScript's weird pseudo object-oriented functional approach is confusing me no end.
What I'm having trouble with is this and why I seem to always need it in every reference to anything in my class. It just seems to result in an inordinate amount of typing in order to write much that is useful in JS and I can't help but feel I must be doing it wrong somehow:
function MyClass()
{
var a=1;
this.b = 2;
this.internalMethod= function()
{
console.log("a is: "+a); // returns "a is: 1"
// console.log("b is: "+b); - this fails because b is undefined
console.log("this.a is: "+this.a); // returns "this.a is: undefined" but doesn't crash.
console.log("this.b is: "+this.b); // returns "this.b is: 2"
}
}
MyClass.prototype.externalMethod = function()
{
// console.log("a is: "+a); - fails
// console.log("b is: "+b); - fails
console.log("this.a is: "+this.a); // "this.a is: undefined"
console.log("this.b is: "+this.b); // "this.b is: 2"
}
var m = new MyClass();
m.internalMethod();
m.externalMethod();
What I am understanding from this is that if I am adding a new public method through the class.prototype approach, I only have access to properties that are defined with this.
If I create an internal method in the class definition function I have access to any var values in the class itself and I can access this.property as long as I include the this.
Is this correct? Do I always have to include an explicit object reference to access properties in any functions that use the prototype method? If so, should I be declaring all my functions within the parent class function rather than using the class.prototype pattern for adding them?
In essence I am looking for a standard approach to managing variable scope when writing object oriented Javascript. Most of the articles I can find on this topic are either basic introductions to object orientation or seem to gloss over this area. A lot of my classes are fairly data intensive and having to make calls in the form this.myMethod( this.firstArray, this.secondArray, this.thirdArray, this.fourthArray ) seems like a long cut and impedes the readability of code.
(I am aware of the var that=this trick for avoiding caller scope problems but I didn't want to mess up my examples with it as as far as I know it's not really pertinent to my question.)
function MyClass()
{
var a=1;
this.b = 2;
this.internalMethod= function()
{
console.log("a is: "+a); // returns "a is: 1"
// console.log("b is: "+b); - this fails because b is undefined
console.log("this.a is: "+this.a); // returns "this.a is: undefined" but doesn't crash.
console.log("this.b is: "+this.b); // returns "this.b is: 2"
}
}
In that code, the first console.log will return the right value, because you declared the variable a and then declared the function, which grabs it's environment and saves it all into something called closure (this explanation might be a bit off), so what happens here, is that when you call internalMethod, that function in it's environment also has the definition of a. Which might be confusing, because when you do your second console.log your see "undefined", which is because the a variable is not an attribute of this, but rather just a global variable to the scope of your internalMethod.
MyClass.prototype.externalMethod = function()
{
// console.log("a is: "+a); - fails
// console.log("b is: "+b); - fails
console.log("this.a is: "+this.a); // "this.a is: undefined"
console.log("this.b is: "+this.b); // "this.b is: 2"
}
In that code, a is not defined, becuase it didn't exist when you declared your method, but this.b does, because is part of the attributes of MyClass, which is what you're working on.
So, to summarize, you'll want to use the this keyword when adding or using internal attributes to your "class" (which you should not call class, since that doesn't exists here). It might be a pain, but it's the only way to reference internal attributes of your objects from within it's methods.
Additionally, you might find these two articles interesting to read, since they explain a bit about OOP techniques for JS and some common mistakes:
Let me know if you have more questions.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With