JS面向物件之封裝
阿新 • • 發佈:2020-12-23
面向物件程式設計思想:
以事物為重心, 考慮的是一件事情的完成有哪些事物參與了, 重點在於完善每種事物. 然後各種事物專案配合完成這件事兒.
面向物件的程式語言:
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
一個例項經歷了四步:
- 建立一個新物件;
- 將建構函式內的
this
繫結到新物件上; - 為新物件新增屬性和方法;
- 返回新物件(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
都一樣了,我們顯然不希望所有例項屬性方法都一樣,它們還是要有自己獨有的屬性方法。並且如果原型中物件中有引用型別值,例項中獲得的都是該值的引用,意味著一個例項修改了這個值,其他例項中的值都會相應改變。 - 解決辦法:建構函式+原型模式組合使用。