1. 程式人生 > 實用技巧 >JS面向物件之封裝

JS面向物件之封裝

面向物件程式設計思想:

  以事物為重心, 考慮的是一件事情的完成有哪些事物參與了, 重點在於完善每種事物. 然後各種事物專案配合完成這件事兒.
面向物件的程式語言:

  Java, C#, Object-C, JavaScript...但是, JavaScript不是嚴格意義上面向物件的語言, 因為沒有類的概念.
面向過程程式設計思想:

  以事件為重心, 考慮的是一件事情的完成需要怎樣的步驟, 每個步驟都需要怎麼處理.

JS是基於物件的若型別語言

在基於類的面向物件方式中,物件(object)依靠類(class)來產生。
在基於原型的面向物件方式中,物件(object)則是依靠建構函式(constructor)和原型(prototype)構造出來的。

JS封裝

面嚮物件語言的第一個特性毫無疑問是封裝,在 JS 中,封裝的過程就是把一些屬性和方法放到物件中“包裹”起來,那麼我們要怎麼去封裝屬性和方法

物件字面量 --> object物件 --> 工廠模式 --> 建構函式 --> 原型模式 --> 建構函式+原型模

物件字面量

   var dog = {
        // 屬性 - 變數 
        color:'white',
        weight:'20kg',
        height:'0.6m',
        // 方法 - 函式 
        eat: function(){
            
return '我要eat飯'; }, sleep: function(){ console.log('我要睡覺'); } } // 呼叫物件 // 調屬性 console.log(dog.color); // 調方法 var res = dog.eat(); console.log(res);

Object方式建立

    var obj1 = new Object();
    // 屬性
    obj1.color = 'white-2';
    obj1.height 
= '0.6m'; // 方法 obj1.eat = function(){ console.log('我要eat飯-2'); } // 呼叫物件 // 調屬性 console.log(obj1.color); var str = 'color'; console.log(obj1[str]); // 注意:物件中的呼叫,.後面不能跟變數,變數需要使用 []
  • 優點:程式碼簡單
  • 缺點: 建立多個物件會產生大量的程式碼,編寫麻煩,且並沒有例項與原型的概念。
  • 解決辦法:工廠模式。

工廠模式

工廠模式是程式設計領域一種廣為人知的設計模式,它抽象了建立具體物件的過程。JS 中建立一個函式,把建立新物件、新增物件屬性、返回物件的過程放到這個函式中,使用者只需呼叫函式來生成物件而無需關注物件建立細節,這叫工廠模式:

function createPerson(name='jack',age=18){ 
        var person = new Object();
        person.name = name;
        person.age = age;

        person.showName = function(){
            console.log('我的名字是:' + this.name);
        }
        person.showAge = function(){
            console.log('我的年齡是:' + this.age);
        }
        return person; // 物件
}
var per = createPerson('xiaoming',33); // person
  • 優點:工廠模式解決了物件字面量建立物件程式碼重複問題,建立相似物件可以使用同一API。
  • 缺點:因為是呼叫函建立物件,無法識別物件的型別。
  • 解決辦法:建構函式

建構函式

function createPer(name='jack',age=18){
        // var obj = new Object();
        // 系統會自動建立
        // var this = new Object();
        this.name = name;
        this.age = age;

        this.showName = function(){
            console.log('我的名字是:' + this.name);
        }
        this.showAge = function(){
            console.log('我的年齡是:' + this.age);
        }
        // 省略:系統幫你自己返回
        // return obj
}
// 建立物件
var person = new createPer('zhangsan',19);

通過建構函式new一個例項經歷了四步:

  1. 建立一個新物件;
  2. 將建構函式內的this繫結到新物件上;
  3. 為新物件新增屬性和方法;
  4. 返回新物件(JS 引擎會預設新增return this;

而通過建構函式建立的物件都有一個constructor屬性,它是一個指向建構函式本身的指標,因此就可以檢測物件的型別啦。:

alert(person.constructor === Person) //true
alert(person instanceof Person) // true

但是仍然存在問題

alert(person.showName == person2.showName) //false
  • 優點:解決了類似物件建立問題,且可以檢測物件型別。
  • 缺點:建構函式方法要在每個例項上新建一次。
  • 解決辦法:原型模式。

原型物件 + 構造物件

    function newPerson(name='jack',age=18){
        this.name = name;
        this.age = age;
    }
    // 原型方法
    // newPerson.prototype.
    newPerson.prototype.showName = function(){
        console.log('我的名字是:' + this.name);
    }
    newPerson.prototype.showAge = function(){
        console.log('我的年齡是:' + this.age);
    }
    // 建立物件
    var zhang = new newPerson('zhangsan',19);
    var peiqi = new newPerson('佩奇',2);
    zhang.showName();
    peiqi.showName();
    console.log(zhang.showName == peiqi.showName); // true
    // 建構函式
    console.log(newPerson.prototype.constructor);
  • 優點:與單純使用建構函式不一樣,原型物件中的方法不會在例項中重新建立一次,節約記憶體。
  • 缺點:使用空建構函式,例項 person1 和 person2 的name都一樣了,我們顯然不希望所有例項屬性方法都一樣,它們還是要有自己獨有的屬性方法。並且如果原型中物件中有引用型別值,例項中獲得的都是該值的引用,意味著一個例項修改了這個值,其他例項中的值都會相應改變。
  • 解決辦法:建構函式+原型模式組合使用。