オブジェクト指向 JavaScript の書き方を検索して読んだ後、以下のコードにまとめました。
/********************************************************/
// Enumeration.
var Fruits = {
    Apple: 0,
    Orange: 1,
    Watermelon: 2,
    Banana: 3
}; // <-- Don't forget ;
// Using enumeration.
// function SquishFruit(fruit) {
//     switch (fruit) {
//         case Fruits.Apple : Chop();
//         case Fruits.Orange : Pulp();
//         case Fruits.Watermelon : Smash();
//         case Fruits.Banana : Peel();
//     }
/********************************************************/
/********************************************************/
// Base class.
function BaseClass(arg) {
    // Constructor.
    alert("I am BaseClass constructor.\n arg=" + arg);
    // Private fields.
    // Use m_privateField, Not this.m_privateField in the class scope.
    var m_privateField = "I am BaseClass.m_privateField";
    // Public fileds.
    // Use this.PublicField, Not PublicField in the class scope.
    this.PublicField = "I am BaseClass.PublicField";
    // Private methods.
    // Invoke PrivateMethod(), Not this.PrivateMethod() in the class scope.
    function PrivateMethod(arg) {
        alert("I am BaseClass.PrivateMethod.\n arg=" + arg + "\n m_privateField=" + m_privateField);
        return;
    }
    // Public methods.
    // ----------------------------------------------------------------------
    // Note: Using "prototype" increases efficiency but breaks the encapsulation.
    // Example:
    // function MyClass() {
    //     var _value = 1;
    // }
    // MyClass.prototype.getValue = function () {
    //     // the function assigned to getValue is
    //     // no longer in scope with _value it can't access it.
    //     return _value;
    // }
    // ----------------------------------------------------------------------
    // Invoke this.PublicMethod(), Not PublicMethod() in the class scope.
    this.PublicMethod = function (arg) {
        alert("I am BaseClass.PublicMethod.\n arg=" + arg + "\n PublicField=" + this.PublicField);
        return;
    };  // <-- Don't forget ;
    // Virtual methods.
    // Invoke this.VirtualMethod(), Not VirtualMethod() in the class scope.
    this.VirtualMethod = function (arg) {
        alert("I am BaseClass.VirtualMethod.\n arg=" + arg + "\n");
        return;
    };  // <-- Don't forget ;
}
// Static fields.
BaseClass.StaticField = "I am BaseClass.StaticField";
// Static methods.
BaseClass.StaticMethod = function (arg) {
    alert("I am BaseClass.StaticMethod.\n arg=" + arg + "\n StaticField=" + BaseClass.StaticField);
    return;
}
/********************************************************/
/********************************************************/
// Derived class.
function DerivedClass(arg) {
    // Call base class constructor.
    // Never forget this call.
    BaseClass.call(this, arg);
    // Constructor.
    alert("I am DerivedClass constructor.\n arg=" + arg);
    // Private fields.
    // Use m_privateField2, Not this.m_privateField2 in the class scope.
    var m_privateField2 = "I am DerivedClass.m_privateField2";
    // Public fileds.
    // Use this.PublicField2, Not PublicField2 in the class scope.
    this.PublicField2 = "I am DerivedClass.PublicField2";
    // Private methods.
    // Invoke PrivateMethod2(), Not this.PrivateMethod2() in the class scope.
    function PrivateMethod2(arg) {
        alert("I am DerivedClass.PrivateMethod.\n arg=" + arg + "\n m_privateField2=" + m_privateField2);
        return;
    }
    // Public methods.
    // Invoke this.PublicMethod2(), Not PublicMethod2() in the class scope.
    this.PublicMethod2 = function (arg) {
        alert("I am DerivedClass.PublicMethod2.\n arg=" + arg + "\n PublicField2=" + this.PublicField2);
        return;
    };  // <-- Don't forget ;
    // Virtual methods.
    // Invoke this.VirtualMethod(), Not VirtualMethod() in the class scope.
    this.VirtualMethod = function (arg) {
        alert("I am DerivedClass.VirtualMethod.\n arg=" + arg + "\n");
        return;
    };  // <-- Don't forget ;
}
// Make DerivedClass derived from BaseClass.
// Never forget these two lines.
// Note: Constructor of BaseClass invoked here.
DerivedClass.prototype = new BaseClass; // () not required!
DerivedClass.prototype.constructor = DerivedClass;
// Static fields.
DerivedClass.StaticField2 = "I am DerivedClass.StaticField2";
// Static methods.
DerivedClass.StaticMethod2 = function (arg) {
    alert("I am DerivedClass.StaticMethod2.\n arg=" + arg + "\n StaticField2=" + DerivedClass.StaticField2);
    return;
}
/********************************************************/
/********************************************************/
// Tests.
alert("---------- Tests started ----------");
// Test enumuration.
var fruit = Fruits.Apple;
alert("Test enumuration.\n fruit=" + fruit);
// Test BaseClass.
var baseClass = new BaseClass("Hello BaseClass.");
// Test private fields.
alert("Test private fields:\n baseClass.m_privateField=" + baseClass.m_privateField); // undefined.
// Test public fields.
alert("Test public fields:\n baseClass.PublicField=" + baseClass.PublicField);
// Test private methods.
// TypeError: baseClass.PrivateMethod is not a function
// baseClass.PrivateMethod("Hello PrivateMethod.");
// Test public methods.
baseClass.PublicMethod("Hello PublicMethod.");
// Test virtual methods.
baseClass.VirtualMethod("Hello VirtualMethod.");
// Test Static fields.
// Note: Use class name instead of objact name.
// BaseClass.StaticField expression is correct.
// baseClass.StaticField expression is incorrect (baseClass.StaticField value is undefined).
alert("Test Static fields:\n BaseClass.StaticField=" + BaseClass.StaticField);
// Test Static methods.
// Note: Use class name instead of objact name.
BaseClass.StaticMethod("Hello StaticMethod.");
// Test DerivedClass.
var derivedClass = new DerivedClass("Hello DerivedClass.");
// Test private fields.
alert("Test private fields:\n derivedClass.m_privateField=" + derivedClass.m_privateField); // undefined.
alert("Test private fields:\n derivedClass.m_privateField2=" + derivedClass.m_privateField2); // undefined.
// Test public fields.
alert("Test public fields:\n derivedClass.PublicField=" + derivedClass.PublicField);
alert("Test public fields:\n derivedClass.PublicField2=" + derivedClass.PublicField2);
// Test private methods.
// TypeError: derivedClass.PrivateMethod is not a function
// derivedClass.PrivateMethod("Hello PrivateMethod.");
// TypeError: derivedClass.PrivateMethod2 is not a function
// derivedClass.PrivateMethod2("Hello PrivateMethod2.");
// Test public methods.
derivedClass.PublicMethod("Hello PublicMethod.");
derivedClass.PublicMethod2("Hello PublicMethod2.");
// Test virtual methods.
derivedClass.VirtualMethod("Hello VirtualMethod.");
// Test Static fields.
// Note: Use class name instead of objact name.
alert("Test Static fields:\n DerivedClass.StaticField=" + DerivedClass.StaticField); // undefined. Use BaseClass.StaticField.
alert("Test Static fields:\n DerivedClass.StaticField2=" + DerivedClass.StaticField2);
// Test Static methods.
// Note: Use class name instead of objact name.
// TypeError: DerivedClass.StaticMethod is not a function
// DerivedClass.StaticMethod("Hello StaticMethod.");
DerivedClass.StaticMethod2("Hello StaticMethod2.");
/********************************************************/
/********************************************************/
// References:
// http://people.apache.org/~martinc/OOP_with_ECMAScript/
// http://stackoverflow.com/questions/107464/is-javascript-object-oriented
// https://developer.mozilla.org/en-US/docs/JavaScript/Introduction_to_Object-Oriented_JavaScript
// https://developer.mozilla.org/en-US/docs/JavaScript/Guide/Details_of_the_Object_Model
/********************************************************/
このコードをテストしたところ、問題なく動作しました。
IE9、FireFox 15、Google Chrome 22 でテストしています。
私が実装できなかった機能のいくつかは次のとおりです。
- 人間が読める形式の名前空間。
 - プライベート静的フィールド。
 - プライベートな静的メソッド。
 
JavaScript でのオブジェクト指向プログラミングについて見逃していることはありますか?それとも、カプセル化、ポリモーフィズム、および継承クラスに関するより良いアイデアはありますか?