javascript面向對象的程式設計-創建對象;理解對象、屬性、方法、引用類型、基本類型、原型模式;創建對象的幾種方法。
javascript的對象:無序屬性的集合,而每個屬性可以包含基本值、對象或者函數。舉例:
1 var person = new Object(); 2 person.name = "Nicholas"; 3 person.age = 29; 4 person.job = "Software Engineer"; 5 person.sayName = function(){ 6 alert(this.name); 7 }; 8 9 person.sayName();
person是一個對象,name、age、job、sayName都是對象的屬性。其中,sayName是一個特殊的屬性,它有一個函數。
實際上,函數也是一個Function類型,是個引用類型,而對象也是一個引用類型,如此可以重新描述javascript對象:對象擁有一些屬性,每個屬性又可以包含基本類型、引用類型。
- 對象的創建:
- 創建一個Object實例,然後添加屬性:
1 var person = new Object(); 2 person.name = "Nicholas"; 3 person.age = 29; 4 person.job = "Software Engineer"; 5 person.sayName = function(){ 6 alert(this.name); 7 }; 8 9 person.sayName();
- 直接使用字面量:
var person={ name : "JAY", age : 29, job : 'singer', sayName : function(){ alert(this.name); } };
- 創建一個Object實例,然後添加屬性:
- 創建對象的策略
- 工廠模式(把創建對象的過程封裝起來,讓代碼更加整潔):
function createPerson(name, age, job){ var o = new Object(); o.name = name; o.age = age; o.job = job; o.sayName = function(){ alert(this.name); }; return o; } var person1 = createPerson("Nicholas", 29, "Software Engineer"); var person2 = createPerson("Greg", 27, "Doctor");
缺點:對象是創建了,但是如果你問person1、person2是什麼類型的,無法識別出。解決方法:構造函數模式。
- 構造函數模式:
function Person(name, age, job){ this.name = name; this.age = age; this.job = job; this.sayName = function(){ alert(this.name); }; } var person1 = new Person("Nicholas", 29, "Software Engineer"); var person2 = new Person("Greg", 27, "Doctor");
- 優點:可以知道對象的類型(Person)。
構造函數也是函數。 任何函數使用new就變成了構造函數(只不過約定俗成構造函數第一個字母大寫),不用new就是一般函數。
- 缺點:sayName是一個函數(函數是對象,是引用類型),每次new一個Person,都要重新創建sayName的實例。解決方法:原型模式。
- 優點:可以知道對象的類型(Person)。
- 原型模式(實例共用屬性和方法)
創建函數時會加屬性,而每個函數都有一個隱藏屬性:prototype(原型)。
prototype是一個指針,指向一個對象,該對象包含了所有實例共用的一些屬性和方法。function Person(){ } Person.prototype.name = "Nicholas"; Person.prototype.age = 29; Person.prototype.job = "Software Engineer"; Person.prototype.sayName = function(){ alert(this.name); }; var person1 = new Person(); person1.sayName(); //"Nicholas" var person2 = new Person(); person2.sayName(); //"Nicholas" alert(person1.sayName == person2.sayName); //true
跟父類很類似。這時,person1和person2的sayName是同一個引用。
- 創建一個新函數A,就會自動為該函數創建prototype屬性。這個屬性指向該函數的原型對象B。
-
B有一個constructor屬性,該屬性包含一個指向A的指針。
- 通過B.isPrototypeof(Person1)來確定原型關係。
- 不能通過對象實例來修改原型的屬性值。
function Person(){ } Person.prototype.name = "Nicholas"; Person.prototype.age = 29; Person.prototype.job = "Software Engineer"; Person.prototype.sayName = function(){ alert(this.name); }; var person1 = new Person(); var person2 = new Person(); person1.name = "Greg"; alert(person1.name); //"Greg" ?from instance alert(person2.name); //"Nicholas" ?from prototype
- 更簡單的原型語法:
function Person(){ } Person.prototype = { name : "Nicholas", age : 29, job: "Software Engineer", sayName : function () { alert(this.name); } };
該方式中,constructor屬性不再指向Person。(因為創建一個函數會生成一個prototype屬性,該屬性指向原型對象的地址,原型對象的constructor屬性又指向Person,而在本方式中,prototype被重寫,那麼導致生成的原型對象B不是原汁原味的原型對象了,這麼一來,B的constructor也就不再指向A了)。
- 工廠模式(把創建對象的過程封裝起來,讓代碼更加整潔):