JavaScript継承の実現

4548 ワード

JavaScriptで簡単な継承はどうやって実現しますか? 
以下の例は従業員タイプのEmployeeを作成します.Personからプロトタイプのすべての属性を継承しました.
function Employee(name, sex, employeeID) {
    this.name = name;
    this.sex = sex;
    this.employeeID = employeeID;
}
//  Employee     Person     
//   Person       Person      ,   Employee        Person        。
Employee.prototype = new Person();
Employee.prototype.getEmployeeID = function() {
    return this.employeeID;
};
var zhang = new Employee("ZhangSan", "man", "1234");
console.log(zhang.getName()); // "ZhangSan
上の継承の実現は粗く、多くの問題があります.
Employeeコンストラクターとプロトタイプ(以後、クラスと略称する)を作成する際に、Personを実例化しました.これは不適切です.Employeeのコンストラクタは父Personのコンストラクタを呼び出すことができず、Employeeコンストラクタにおけるnameとsex属性に対する重複した割り当てをもたらします.Employeeの関数はPersonの同名の関数をカバーします.再負荷のメカニズムはありません.JavaScript類を作るには文法があまりにも散漫で、C嗳/Javaの中の文法が優雅ではないです.実現中にconstructor属性の指差があります.JavaScript自体は完全なクラスと継承の実現がないだけに、私達も手作りで実現する方法に多くの問題があることを見ています.これに対して挑戦的な任務はネット上ですでにたくさん実現されました.
Duglas Crockford- Prottypal Inherityance in JavaScript Duglas Crockford- Clashical Inherityance in JavaScript John Resig- Simple JavaScript Inhersitance Dean Edwards- A Base Class for JavaScript Inhersitance Prottype Mootools Extjs この文章は実行可能な実例コードを提供して、具体的にこれらの実現を分析して、最終的にJavaScriptの中でどのように種類と継承を実現しますか?JavaScriptを理解するのに一定の助けがあることを望みます.
( function() {
    jClass = function() {
    };
    //             
    var initializing = false;
    jClass.extend = function( prop ) {
        var baseClass = null;
        //            (     )  Class,    
        if ( this !== jClass ) {
            baseClass = this;
        }
        //          (    )
        var jConstructor = function() {
            //              ,   init    
            if ( !initializing ) {
                //       ,      baseprototype       
                //                     
                if ( baseClass ) {
                    this._superprototype = baseClass.prototype;
                }
                this.init.apply( this, arguments );
            }
        }
        //             
        if ( baseClass ) {
            initializing = true;
            jConstructor.prototype = new baseClass();
            jConstructor.prototype.constructor = jConstructor;
            initializing = false;
        }
        //          extend  
        jConstructor.extend = arguments.callee;

        //          
        for ( var name in prop ) {
            if ( prop.hasOwnProperty( name ) ) {
                //          baseClass,             name
                if ( baseClass &&
                        typeof ( prop[name] ) === "function" &&
                        typeof ( jConstructor.prototype[name] ) === "function" &&
                        /\b_super\b/.test( prop[name] ) ) {
                    //      name - 
                    //           this._super            
                    //       prop[name],      
                    //   :                ,            ,
                    //                 ,     (Closure)。
                    //   JavaScript          。
                    jConstructor.prototype[name] = ( function( name, fn ) {
                        return function() {
                            this._super = baseClass.prototype[name];
                            return fn.apply( this, arguments );
                        };
                    } )( name, prop[name] );
                } else {
                    jConstructor.prototype[name] = prop[name];
                }
            }
        }
        return jConstructor;
    };
} )();


// Demo
var Person = jClass.extend( {
    init: function( name ) {
        this.name = name;
    },
    getName: function( prefix ) {
        return prefix + this.name;
    }
} );
var Employee = Person.extend( {
    init: function( name, employeeID ) {
        //         
        this._super( name );
        this.employeeID = employeeID;
    },
    getEmployeeIDName: function() {
        //   :                     
        var name = this._superprototype.getName.call( this, "Employee name: " );
        return name + ", Employee ID: " + this.employeeID;
    },
    getName: function() {
        //         
        return this._super( "Employee name: " );
    }
} );

var zhang = new Employee( "ZhangSan", "1234" );
console.log( zhang.getName( ) );   // "Employee name: ZhangSan"
console.log( zhang.getEmployeeIDName() ); // "Employee name: ZhangSan, Employee ID: 1234"