面向對象的Javascript之三(封裝和信息隱藏)
2024-05-06 14:22:33
供稿:網友
同時,我們知道在面向對象的高級語言中,創建包含私有成員的對象是最基本的特性之一,提供屬性和方法對私有成員進行訪問來隱藏內部的細節。雖然JS也是面向對象的,但沒有內部機制可以直接表明一個成員是公有還是私有的。還是那句話,依靠JS的語言靈活性,我們可以創建公共、私有和特權成員,信息隱藏是我們要實現的目標,而封裝是我們實現這個目標的方法。我們還是從一個示例來說明:創建一個類來存儲圖書數據,并實現可以在網頁中顯示這些數據。
1. 最簡單的是完全暴露對象。使用構造函數創建一個類,其中所有的屬性和方法在外部都是可以訪問的。
代碼如下:
var Book = function(isbn, title, author) {
if(isbn == undefined) {
throw new Error("Book constructor requires a isbn.");
}
this.isbn = isbn;
this.title = title || "";
this.author = author || "";
}
Book.prototype.display = function() {
return "Book: ISBN: " + this.isbn + ",Title: " + this.title + ",Author: " + this.author;
}
display方法依賴于isbn是否正確,如果不是你將無法獲取圖像以及鏈接??紤]到這點,每本圖書isbn必須存在的,而圖書的標題和作者是可選的。表面上看只要指定一個isbn參數似乎就能正常運行。但卻不能保證isbn的完整性,基于此我們加入isbn的驗證,使圖書的檢查更加健壯。
代碼如下:
var Book = function(isbn, title, author) {
if(!this.checkIsbn(isbn)) {
throw new Error("Book: invalid ISBN.");
}
this.isbn = isbn;
this.title = title || "";
this.author = author || "";
}
Book.prototype = {
checkIsbn: function(isbn) {
if(isbn == undefined || typeof isbn != "string") return false;
isbn = isbn.replace("-", "");
if(isbn.length != 10 && isbn.length != 13) return false;
var sum = 0;
if(isbn.length == 10) {
if(!isbn.match(/^/d{9}/)) return false;
for(var i = 0;i < 9;i++) {
sum += isbn.charAt(i) * (10 - i);
}
var checksum = sum % 11;
if(checksum == 10) checksum = "X";
if(isbn.charAt(9) != checksum) return false;
} else {
if(!isbn.match(/^/d{12}/)) return false;
for(var i = 0;i < 12;i++) {
sum += isbn.charAt(i) * (i % 2 == 0 ? 1 : 3);
}
var checksum = sum % 10;
if(isbn.charAt(12) != checksum) return false;
}
return true;
},
display: function() {
return "Book: ISBN: " + this.isbn + ",Title: " + this.title + ",Author: " + this.author;
}
};
我們添加了checkIsbn()來驗證ISBN的有效性,確保display()可以正常運行。但是需求有變化了,每本書可能有多個版本,意味著同一本可能有多個ISBN號存在,需要維護單獨的選擇版本的算法來控制。同時盡管能檢查數據的完整性,但卻無法控制外部對內部成員的訪問(如對isbn,title,author賦值),就談不上保護內部數據了。我們繼續改進這個方案,采用接口實現(提供get訪問器/set存儲器)。