一、 生成對象的原始模式假定我們把Bob看成一個對象,它有"name"和"age"兩個屬性。 var person = { name : '', age : }現在,我們需要根據這個原型對象的規格(schema),生成兩個實例對象。 var person1 = {}; // 創建...
一、 生成對象的原始模式
假定我們把Bob看成一個對象,它有"name"和"age"兩個屬性。
var person = {
name : '',
age :
}
現在,我們需要根據這個原型對象的規格(schema),生成兩個實例對象。
var person1 = {}; // 創建一個空對象
person1.name = "Bob"; // 按照原型對象的屬性賦值
person1.age= 18;
var person2 = {};
person2.name = "jim";
person2.age = 20;
好了,這就是最簡單的封裝了,把兩個屬性封裝在一個對象裡面。但是,這樣的寫法有兩個缺點,一是如果多生成幾個實例,寫起來就非常麻煩;二是實例與原型之間,沒有任何辦法,可以看出有什麼聯繫。
二、 原始模式的改進
我們可以寫一個函數,解決代碼重覆的問題。
function person(name,age){
return {
name:name,
age:age
}
然後生成實例對象,就等於是在調用函數:
var person1 = person("Bob",18);
var person2 = person("jim",20);
這種方法的問題依然是,person1和person2之間沒有內在的聯繫,不能反映出它們是同一個原型對象的實例。
三、 構造函數模式
為瞭解決從原型對象生成實例的問題,Javascript提供了一個構造函數(Constructor)模式。
所謂"構造函數",其實就是一個普通函數,但是內部使用了this變數。對構造函數使用new運算符,就能生成實例,並且this變數會綁定在實例對象上。
比如,person的原型對象現在可以這樣寫,
function person(name,age){
this.name=name;
this.age=age;
}
我們現在就可以生成實例對象了。
var person1 = new person("Bob",18);
var person2 = new person("jim",20);
alert(person1.name); // Bob
alert(person1.age); // 18
這時person1和person2會自動含有一個constructor屬性,指向它們的構造函數
alert(person1.constructor == person); //true
alert(person2.constructor == person); //true
Javascript還提供了一個instanceof運算符,驗證原型對象與實例對象之間的關係。
alert(person1 instanceof person); //true
alert(person2 instanceof person); //true
四、構造函數模式的問題
構造函數方法很好用,但是存在一個浪費記憶體的問題。
請看,我們現在為Cat對象添加一個不變的屬性"type"(種類),再添加一個方法lesson(課程)。那麼,原型對象person就變成了下麵這樣:
function person(name,age){
this.name = name;
this.age= age;
this.type = "理科";
this.lesson = function(){alert("課程");};
}
還是採用同樣的方法,生成實例:
var person1 = new person("Bob",18);
var person2 = new person ("jim",20);
alert(person1.type); // 理科
person1.lesson(); // 課程
能不能讓type屬性和lesson()方法在記憶體中只生成一次,然後所有實例都指向那個記憶體地址呢?回答是可以的。
五、 Prototype模式
Javascript規定,每一個構造函數都有一個prototype屬性,指向另一個對象。這個對象的所有屬性和方法,都會被構造函數的實例繼承。
這意味著,我們可以把那些不變的屬性和方法,直接定義在prototype對象上。
function person(name,age){
this.name = name;
this.age= age;
}
person.prototype.type = "理科";
person.prototype.lesson = function(){alert("課程")};
然後,生成實例。
var person1 = new person("Bob",18);
var person2 = new person("jim",20);
alert(person1.type); // 理科
person1.lesson(); // 課程
這時所有實例的type屬性和lesson()方法,其實都是同一個記憶體地址,指向prototype對象,因此就提高了運行效率。
alert(person1.lesson== person2.lesson); //true
六、 Prototype模式的驗證方法
為了配合prototype屬性,Javascript定義了一些輔助方法,幫助我們使用它。,
6.1 isPrototypeOf()
這個方法用來判斷,某個proptotype對象和某個實例之間的關係。
alert(person.prototype.isPrototypeOf(person1)); //true
alert(person.prototype.isPrototypeOf(person2)); //true
6.2 hasOwnProperty()
每個實例對象都有一個hasOwnProperty()方法,用來判斷某一個屬性到底是本地屬性,還是繼承自prototype對象的屬性。
alert(person1.hasOwnProperty("name")); // true
alert(person1.hasOwnProperty("type")); // false
6.3 in運算符
in運算符可以用來判斷,某個實例是否含有某個屬性,不管是不是本地屬性。
alert("name" in person1); // true
alert("type" in person1); // true
in運算符還可以用來遍歷某個對象的所有屬性。
for(var prop in cat1) { alert("cat1["+prop+"]="+cat1[prop]); }