JavaScript library pattern
I'm trying to figure out the basic pattern for creating a JavaScript library (class). I want to do it in such a way that it doesn't pollute the global namespace with a bunch of junk, but allowing for the class to have instance variables and public methods that modify those instance variables.
Consider the following toy example. I want to make a class Foo
. It should contain an instance member, bar
, which is a number. There should be a constructor for Foo
that takes a numb开发者_如何学Pythoner and initializes its instance bar
with that number. There should be an instance method that I can call on a Foo
object to modify bar
. Maybe the code that uses the library looks like this:
var foo1 = new Foo(1);
var foo2 = new Foo(2);
console.log(foo1.bar); // should print "1"
console.log(foo2.bar); // should print "2"
foo2.changeBar(42);
console.log(foo1.bar); // should print "1"
console.log(foo2.bar); // should print "42"
The resultant foo.js
would be used by a Web app and therefore included via a script tag in the HTML.
I've done a bit of searching with Google but I have yet to find a single, concise, generic outline of how to design a JavaScript class (used as a library).
(function () {
Foo = function (num) {
this.changeBar(num);
};
var privateMethod = function (x) {
if (this.bar === 999) {
this.bar = x;
}
};
Foo.prototype.changeBar = function (num) {
this.bar = num;
privateMethod.call(this, 1);
};
}());
That is the simplest way of doing it. You don't need to include the definition in a closure, more of a style thing.
Building up on Evan's answer, to showcase some more possibilites. Most normal cases only use some of these though.
(function() {
//When we create variables inside a function they can only be seen by other
// inner functions. Wraping all our code here makes sure noone gets to see
// the private stuff.
//The first opening parenthesis is required for Javascript to parse it
//correctly though
//this is the constructor function
//Note how we set a global variable (Foo) to make it available outside.
Foo = function(num, another_num) {
this.changeBar(num);
//sometimes you will want to make a method that modifies a variable
//that can't be acessed via this.xxx. You can use a closure here for that
//(there are some performance considerations though)
this.baz = function(){
console.log(another_num);
}
//Setting methods "by hand" like this is also useful if you want to
//do multiple inheritance, since you can just set all methods of the
//second class by hand here if you want.
}
//Things on Foo.prototype will be available for all Foo objects,
// via prototypal inheritance magic.
Foo.prototype.changeBar = function(num) {
this.bar = num;
}
var a_secret_variable = 42;
function my_private_function(){
console.log(a_secret_variable);
}
//All private variables can be normaly used (by functions that can see them).
Foo.prototype.use_magic = function(){
my_private_function();
}
}());
//The "fake" function is imediatelly called,
//so in the end all it does is create a inner scope.
The Module Pattern is probably the most popular pattern used today.
var Foo = (function() {
var _thisIsAPrivateVar;
function thisIsAPrivateMethod() {
}
return {
thisIsAPublicMethod : function() {
// can still access the "private" variable and method
}
};
})();
精彩评论