Reputation: 90756
I'm trying to understand how to best use the JavaScript module pattern. My problem is that it seems there's no way to refer to the module from within itself, because this
is set to the Window
object.
I've got this simple test code:
var Test = function() {
var that = this;
return {
something: function() {
console.info(that);
}
}
}
var test1 = Test();
test1.something();
var test2 = Test();
test2.something();
Both test1
and test2
print a reference to the Window
object instead of the module itself.
Any idea how to change it so that I have a valid this
inside the module?
Upvotes: 2
Views: 81
Reputation: 98786
I think you're confusing the JavaScript module pattern with JavaScript constructor functions.
If you write a function and call it with the new
keyword in front of it, then that function is called as a constructor function.
It will automatically return a new object, that you can refer to within the constructor function using the this
keyword.
var Test = function() {
var that = this;
this.something = function () {
console.info(that);
console.info(this);
};
}
var test1 = new Test();
test1.something();
You can return your own object instead, but you wouldn't normally do that in a constructor, you'd just use this
instead:
var Test = function() {
var that = this;
return {
something: function () {
console.info(that);
console.info(this);
}
};
}
var test1 = new Test();
test1.something();
If you don't call it with the new
keyword in front of it, then it's called like a regular function, meaning any references to this
inside of it refer to the object of which the function is a property (which, in the absence of anything else, will be the global object, which in web browsers is window
).
var geoff = {
Test: function () {
var that = this;
return {
something: function () {
console.info(that);
}
};
}
};
var test2 = geoff.Test();
var test3 = Test();
Note: with constructor functions, you'd normally define methods on their prototype object, so that the methods don't get unnecessarily redefined for each object you create using the constructor function:
var Test = function() {
this.else = "Something Else"
}
Test.prototype.something = function () {
console.info(this);
}
Test.prototype.somethingElse = function () {
console.info(this.else);
}
var test4 = new Test();
test1.somethingElse() // Logs "Something Else"
(Note that if you return your own object from the constructor function as we mentioned above, then you won't be able to access methods on the prototype object any more.)
Also note that each time you call a constructor function, it returns a new object. You can pass parameters into a constructor function (just like you can with any other function) and use them to customise the object returned:
var Test = function(else) {
this.else = else;
}
Test.prototype.somethingElse = function () {
console.info(this.else);
}
var test1 = new Test("Something else");
var test2 = new Test("Something else again");
test1.somethingElse(); // Logs "Something else"
test2.somethingElse(); // Logs "Something else again"
Upvotes: 1
Reputation: 14222
The problem you have is because this
refers to an object, but Test()
isn't an object; it's just a function. The object that owns Test()
is the Window
object (because Test is in the global scope), so therefore that's what you get back when you reference this
from within Test()
.
You may want to try something like this:
var testObj = {
Test : function() {
var that = this;
return {
something: function() {
console.info(that);
}
}
}
}
Now you can call testObj.Test();
and you'll get a reference back to the testObj
object.
Hope that clarifies things a bit.
Upvotes: 0
Reputation: 5917
If you did
var test1 = new Test()
You could then do
test1.something();
An alternative module structure would be to do something like this:
var myModule = function () {
var obj = {};
obj.something = function () {
return console.log(obj);
};
obj.something2 = function () {
return console.log(obj === this); // true
};
return obj;
};
var test = myModule();
test.something();
test.something2();
Hope this helps
Upvotes: 3