封裝是物件導向的重要概念之一。如果一個程式沒有封裝性,也就談不上什麼物件導向。但是, JavaScript並不像其他的語言,比如 Java,有公有變數和私人變數等;在JavaScript中只有一種範圍 :公有範圍。在本章中,我們將會見識到JavaScript是如何?封裝的特性的。
1.this和公 有變數
首先需要理解this關鍵字。看下面的一段代碼,你應該對此感到熟悉:
function Person(name, age) {
this.name = name; // 定義一個公有變數
this.age = age;
this.show = function() { // 定義一個公有函數
alert("name: " + name + "; age: " + age);
}
}
var bill = new Person("Bill", 20);
alert(bill.name);
bill.show();
這裡的this關鍵字是必不可少的。前面只是讓大家記住,那麼為什麼要 這樣呢?想想JavaScript的對象,JavaScript的對象類似於散列,一個<string, object>鍵-值對 的集合。這裡的對象的屬性實際上都是離散的,並不像其他的語言那樣綁定到一個對象上面。this關鍵 字指代的是屬性或者函數的調用者,也就是說,誰調用這個屬性或者函數指的就是誰。可以看到,這裡 的this和Java或者C++的this是有所不同的,後者的this是指屬性或者函數所在的那個對象本身。而這裡 this的作用就是將它後面跟著的屬性或者對象綁定到調用者上面。回憶一下JavaScript的new的過程,首 先將建立一個空的對象,然後使用建構函式初始化這個對象,最後返回這個對象。在這個過程中, JavaScript將把this用這個對象替換,也就是把對象和這些屬性或函數相關聯,看上去就像是這個調用 者擁有這個屬性或者函數似的,其實這是this的作用。
這樣看來,show裡面的name和age並沒有 關鍵字,但也是可以正常的執行就會明白怎麼回事了——因為前面已經用this把name和age與 這個對象bill相關聯,並且,show也關聯到這個bill變數,因此JavaScript是可以找到這兩個變數的。
似乎由this修飾的都是公有變數。事實確實如此,如果你要使一個變數成為公有變數,可以使用 this。像上面代碼中的name和age都是公有變數,在外面使用aPerson.name或者aPerson.age就可以訪問 到。
2.私人變數
怎麼聲明一個私人變數呢?事實上就像前面說的,JavaScript根本沒有 私人範圍這一說。那麼來看下面的代碼:
function Person(name, age) {
var name = name; // 私人屬性
var age = age;
var show = function() { // 私人函數
alert("name: " + name + "; age: " + age);
}
}
var bill = new Person("Bill", 20);
alert(bill.name); // undefined
bill.show(); // error, 不存在
這段代碼和前面幾乎是相同 的,只是把屬性前面的this換成了var。我們知道,var是用來聲明變數的。show函數和bill.name都是未 定義!這是怎麼回事呢?
回憶一下前面說過的JavaScript的new的過程。由於name和age都是使用 var聲明的,JavaScript會將它看作是一個普通的變數,這樣在構造初始化結束之後,建構函式就返回了 ,變數因超出範圍而訪問不到。也就是說,我們使用JavaScript變數範圍類比了私人屬性。
3.靜態變數
靜態變數是綁定到類上面的。對於不同的對象來說,它們共用一個靜態變數 。
Person.num = 0; // 靜態屬性
function Person() {
this.show = function() {
alert("num: " + Person.num);
};
Person.num++;
}
var bill = new Person();
bill.show(); // 1
var tom = new Person ();
tom.show(); // 2
bill.show(); // 2
在JavaScript中可以很方便的添 加靜態屬性,因為JavaScript的對象就是散列,所以只要簡單的在類名後添加一個屬性或者函數即可。