JavaScript模擬物件導向

sz_bdqn發表於2010-09-29

JavaScript模擬物件導向

 

1.      

//建立一個Person

var Person= function(name,sex){

       this._name = name;

       this._sex = sex;

}

//建立一個Person物件

var person = new Person(“狂奔”,’’);

 

2.       私有變數

var Person = function(name,sex){

this._name = name;

this._sex = sex;

 

var _age,_address; //私有變數

this.setAge = function(age){

    this_age = age;

}

this.getAge = function(){

    return _age;

}

…….

}

 

 

3.       公共變數

//建立一個Person

var Person= function(name,sex,age){

       this._name = name;

       this._sex = sex;

this.age = age; //公有變數

}

Person.prototype = {

country:’中國’, //公共變數

display:function(){

   alert(this.country);

}

}

 

 

4.       靜態變數

var Person= function(name,sex,age){

       this._name = name;

       this._sex = sex;

       Person.country = "中國";

}

 

//呼叫靜態變數

new Person();

alert(Person.country);                  

 

5.       私有方法

var Person= function(name,sex){

       this._name = name;

       this._sex = sex;

 

    //私有方法

       var checkEmail = function(){

              return true;

       }

}

 

 

6.       公共方法

var Person= function(name,sex){

       this._name = name;

       this._sex = sex;

}

 

Person.prototype = {

   //公共方法

   add:function(){

    alert(“執行【新增】操作!”);

}

}

//呼叫公共方法

new Person(“狂奔”,””).add();

 

 

7.       靜態方法

var Person= function(name,sex){

       this._name = name;

       this._sex = sex;

 

       Person.converToCase = function(_name){

              alert("["+_name+"]轉換成大寫!");

       }

}

//呼叫靜態方法

new Person();

Person.converToCase(“shangwu”);

 

 

 

8.       JS 模式私有變數、方法、靜態變數、方法、公共變數、方法完整的例子

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml">

<head>

<meta http-equiv="Content-Type" content="text/html; charset=gb2312" />

<title>JS 模式私有變數、方法、靜態變數、方法、公共變數、方法完整的例子</title>

<script type="text/javascript">

var Person = function(_name,_sex){

 

         /*********************************************************************************

          *     私有屬性

          *********************************************************************************/

         var age,address,phone,email;

         var checkPhone = function(){

                   return true;

         }

         var checkEmail = function(){

                   return true;

         }

         /********************************* 私有屬性 end **********************************/

 

        

         /*********************************************************************************

          *     這些屬於特權方法,因為他們是公共方法,但可以訪問私有屬性及私有變數

          *********************************************************************************/

         //姓名

         this.setName = function(_name){

                   name = _name || 'No name specified';

         }

         this.getName = function(){

                   return name;

         }

        

         //性別

         this.setSex = function(_sex){

                   sex = _sex || 'No sex specified';

         }

         this.getSex = function(){

                   return sex;

         }

        

         //年齡

         this.setAge = function(_age){

                   age = _age; // || 'No age specified';

         }

         this.getAge = function(){

                   return age;

         }

        

        

         //地址

         this.setAddress = function(_address){

                   address = _address || 'No address specified';

         }

         this.getAddress = function(){

                   return address;

         }

        

         //電話

         this.setPhone = function(_phone){

                   phone = _phone || 'No phone specified';

         }

         this.getPhone = function(){

                   return phone;

         }

        

         //郵件

         this.setEmail = function(_email){

                   if(!checkEmail(_email))

                            throw new Error('Book: Invalid ISBN');

                   email = _email || 'No email specified';

         }

         this.getEmail = function(){

                   return email;

         }

         /****************************特權方法結束****************************************/

        

        

        

         /*********************************************************************************

          *     靜態變數、靜態方法

          *********************************************************************************/

         Person.country = "中國";

         Person.converToCase = function(_name){

                   alert("["+_name+"]轉換成大寫!");

         }      

         /***********************************靜態變數、靜態方法 end************************/

        

        

         /*********************************************************************************

          *     常量:是一些不能被修改的變數,

          *  js中,可以通過建立只有取值器而沒有賦值器的私有變數來模仿常量。

          *********************************************************************************/

         var Max = 154;

         Person.getMax = function(){

                   return Max;

         }

         //若要使用多個常量可以如下:

         var constants = {UPPER:100,LOWER:-100};

         Person.getConstant = function(_name){

                   return constants[_name];

         }

         /****************************** 常量 end *****************************************/

        

         //構造方法設定屬性

         this.setName(_name);

         this.setSex(_sex);

}

 

/*********************************************************************************

 *     公共屬性、方法,不可以訪問私有變數、私有方法

 *********************************************************************************/

Person.prototype = {

         display:function(){

                   var personInfo = "姓名:"+this.getName()+" 性別:"+this.getSex()+" 年齡:"

                                                                 +this.getAge()+" 地址:"+this.getAddress()+" 電子郵件:"

+ this.getEmail();

                   alert(personInfo);

         },

         add:function(){

                   alert('執行[新增]操作!');

         },

         edit:function(){

                   alert('執行[編輯]操作!');

         },

         del:function(){

                   alert("執行[刪除]操作!");

         }

};

 

//建立Person例項、設定例項方法、呼叫例項方法

var p = new Person('狂奔','');

p.setAge(18);

p.setAddress("深圳");

p.setEmail("shenzhen_zsw@163.com");

p.display();

p.add();

p.edit();

p.del();

 

//呼叫常量

alert(Person.getMax());

alert(Person.getConstant('LOWER'));

 

//呼叫靜態變數、靜態方法

alert(Person.country);                        

Person.converToCase(p.getName());

 

</script>

</head>

 

<body>

</body>

</html>

 

 

9.       介面

 

 

/**

 * name:指的是介面名稱

 * methods:指的是介面中定義的方法如:["add","edit","del"]

 */

var Interface = function(name,methods){

     if(arguments.length!=2){

         throw new Error("介面建構函式包含" + arguments.length + "引數,但必須是是個!");

     }

    

     this.name = name;

     this.methods = [];

     for(var i = 0, len = methods.length; i < len; i++){

         if(typeof methods[i] !== 'string'){

              throw new Error("結構建構函式中定義的方法名必須是字串型別");

         }

         this.methods.push(methods[i]);

     }

};

 

Interface.ensureImplements = function(object){

     if(arguments.length < 2){

         throw new Error("Function Interface.ensureImplements called with " + arguments.length + "arguments,but expected at least 2.");

     }

     for(var i = 1,len = arguments.length; i<len; i++){

         var interface = arguments[i];

         if(interface.constructor !== Interface){

              throw new Error("Function Interface.ensureImplements expects arguments two and above to be instances of Interface.");

         }

        

         for(var j = 0,methodsLen = interface.methods.length; j < methodsLen; j++){

             var method = interface.methods[j];

              if(!object[method] || typeof object[method] !== 'function'){

                  throw new Error("Function Interface.ensureImplements : object does not implement "

                   +"the interface.name interface.Method" + method + " was not found.");

              }

         }

     }

}

 

介面使用的例子:

var PiJiu = new Interface('PiJiu',['getDisplay']);

var JinWei = function(){

     this.name = "金威啤酒";

}

JinWei.prototype = {

    getDisplay : function(){

         return "你好,我是["+this.name+"]";     

     }

};

var QingDao = function(){

    this.name = "青島啤酒";

}

QingDao.prototype = {

    getDisplay : function(){

         return "你好,我是["+this.name+"]";

     }

}

 

var PinJiuFactory = function(pjObj){

     Interface.ensureImplements(pjObj,PiJiu);   

     this.pj = pjObj;  

}

PinJiuFactory.prototype = {

    getPiJiu : function(){

        var str = this.pj.getDisplay();

        alert(str);

     }

};

 

var qingDaoPJ = new QingDao();

var jinWeiPJ = new JinWei();

var testPj = new PinJiuFactory(qingDaoPJ);

testPj.getPiJiu();

 

testPj = new PinJiuFactory(jinWeiPJ);

testPj.getPiJiu();

 

10.   繼承

類式繼承 原型鏈

function Person(name){

    this.name = name;

}

Person.prototype.getName = function(){

    return this.name;

}

 

function Author(name,books){

    Person.call(this,name); //呼叫父類的建構函式,並將name引數傳給它

     this.books = books;

}

 

 

/*

  設定原型鏈,JavaScript中每個物件都有一個名為prototype的屬性這個屬性要麼只想另一個物件,要麼是null

  為了讓一個類繼承另一個類,只是將子類的prototype設定為指向超類的一個例項。

  為了讓Author繼承Person類,必須手工將Authorprototype屬性設定為Person的一個例項。

  最後一個步驟是將prototypeconstructor屬性設定為Person的例項時,其constructor屬性被抹除了。

*/

Author.prototype = new Person();

Author.prototype.constructor = Author;

Author.prototype.getBooks = function(){

     return this.books;

}

 

/*

 *  指的注意的是,在執行Person.call(this,name);這一步的時候我們已經把name * 這個屬性拷貝到Person裡面了,這裡我們不在需要new Person()裡面的這個null * name,所以直接把他們刪除,免得浪費記憶體

*/

delete Author.prototype.name;

 

var author = new Author("閆巨集","Java與模式");

alert(author.getName());

alert(author.getBooks());

 

類式繼承 – extend函式

/*

  把派生子類的的整個過程包裝在一個名為extend的函式中,

  它的作用與其他語言中的extend函式類似,

  即基於一個給定的類建立一個新物件的類。

  實現步驟:

  1.設定prototype

  2.在將constructor重設定為恰當的值

  3.做了一項改進,它新增了一個空函式F,並將用它建立一個物件的例項插入到原型鏈中。

    這樣做可以避免建立類的新例項,以為可能會比較龐大,而且有時超類的建構函式有一些副作用,

     或者會執行一些需要進行大量計算的任務。

*/

function extend(subClass,superClass){

    var F = function(){};

    F.prototype = superClass.prototype;

    subClass.prototype = new F();

     subClass.prototype.constructor = subClass;

}

 

/*----- extend函式的用法--------*/

function Person(_name){

    this.name = _name;

}

Person.prototype.getName = function(){

    return this.name;

}

 

function Author(_name,_books){

   Person.call(this,_name);

   this.books = _books;

}

extend(Author,Person);

Person.prototype.getBooks = function(){

    return this.books;

}

 

var author = new Author("閆巨集","Java與模式");

alert(author.getName());

alert(author.getBooks());

 

 

/*

   在這裡,不需要手工設定prototypeconstructor屬性,

   而是通過在類宣告之後(在向prototype新增任何方法之前)立即呼叫extend函式,

   可以達到同樣的目的。

   不過還是有一個問題,超類的名稱被固有化在子類的宣告之中。

   下面會對extend進行改進

  

*/

 

類式繼承 extend函式的改進

/*

 * 在此記錄中,他提供了superclass屬性,這個屬性可以用來使用者子類與父類之間的耦合。

 * 有了superclass屬性,就可以直接呼叫父類超類中的方法。

 * 如果既要重定義超類的某個方法而又想訪問其在超類中的實現時可以派上用場)

*/

function extend(subClass,superClass){

    var F = function(){};

     F.prototype = superClass.prototype;

     subClass.prototype = new F();

     subClass.prototype.constructor = subClass;

    

    

     subClass.superclass = superClass.prototype;

    if(superClass.prototype.construtor == Object.prototype.constructor){

        superClass.prototype.constructor = superClass;

    }

}

 

/*此函式的用法*/

function Person(_name){

    this.name = _name;

}

Person.prototype.getName = function(){

    return this.name;

}

 

function Author(_name,_books){

    Author.superclass.constructor.call(this,_name);

     this.books = _books;

}

extend(Author,Person);

Author.prototype.getBooks = function(){

    return this.books;

}

 

var test = new Author("閆巨集","Java與模式");

alert(test.getName());

alert(test.getBooks());

 

相關文章