原文地址:http://dean.edwards.name/weblog/2006/03/base/
NB. I’ve amended the code samples below to reflect recent changes in this class.
I’m anOOprogrammer at heart and JavaScript supports prototype based inheritance. Unfortunatley this leads to verbose class definitions:
function Animal(name) {}; Animal.prototype.eat = function() {}; Animal.prototype.say = function(message) {};
I want a nice base class for JavaScriptOO:
I’ve created a JavaScript class (Base.js) that I hope eases the pain of JavaScriptOO. It’s a simple class and extends theObjectobject by adding two instance methods and one class method.
TheBaseclass defines two instance methods:
Call this method to extend an object with another interface:
var object = new Base; object.extend({ value: "some data", method: function() { alert("Hello World!"); } }); object.method(); // ==> Hello World!
If a method has been overridden then thebasemethod provides access to the overridden method:
var object = new Base; object.method = function() { alert("Hello World!"); }; object.extend({ method: function() { // call the "super" method this.base(); // add some code alert("Hello again!"); } }); object.method(); // ==> Hello World! // ==> Hello again!
You can also call thebasemethod from within a constructor function.
Classes are created by calling theextendmethod on theBaseclass:
var Animal = Base.extend({ constructor: function(name) { this.name = name; }, name: "", eat: function() { this.say("Yum!"); }, say: function(message) { alert(this.name + ": " + message); } });
All classes created in this manner will inherit theextendmethod so we can easily subclass theAnimalclass:
var Cat = Animal.extend({ eat: function(food) { if (food instanceof Mouse) this.base(); else this.say("Yuk! I only eat mice."); } }); var Mouse = Animal.extend();
A second parameter passed to theextendmethod of a class defines the class interface:
var Circle = Shape.extend({ // instance interface constructor: function(x, y, radius) { this.base(x, y); this.radius = radius; }, radius: 0, getCircumference: function() { return 2 * Circle.PI * this.radius; } }, { // class interface PI: 3.14 });
Note the use of thebasemethod in the constructor. This ensures that theShapeconstructor is also called. Some other things to note:
Some developers prefer to create classes where methods access private data:
function Circle(radius) { this.getCircumference = function() { return 2 * Math.PI * radius; }; };
You can achieve the same result using the Base class:
var Circle = Shape.extend({ constructor: function(radius) { this.extend({ getCircumference: function() { return 2 * Math.PI * radius; } }); } });
The code is slightly more verbose in this case but you get access to thebasemethod which I find incredibly useful.
I changed my mind a lot about this but finally decided to allow the creation of single instance classes by defining anullconstructor:
var Math = Base.extend({ constructor: null, PI: 3.14, sqr: function(number) { return number * number; } });
This supersedes my oldOOframework which was not as cross-browser as I would have liked (and had other shortcomings).
I have a development area where I’m developing bits and pieces based on this engine. Most of this is work in progress but illustrates the flexibility of this technique.
You can grab theBaseclass here: Base.js.