0

在搜索并阅读了有关如何编写面向对象的 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 中的面向对象编程的任何内容,或者对于封装、多态性和继承类有更好的想法吗?

4

1 回答 1

2

这是我使用的 JavaScript 中一个很好的结构,具有很好的封装和抽象。

    var musicPlayer = {
               init: function(target_items, name){
                  //do something
                  anotherFunction('test');
                },
                anotherFunction(argument){
                }
    };
    $(document).ready(function(){
         musicPlayer.init('.container', 'tooltip');

    });
于 2012-10-02T17:31:05.587 回答