ECMAScript有兩種開發模式:1.函數式(過程化);2.面向對象(OOP);
一 創建對象
1.普通的創建對象
2. 工廠模式創建對象
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 // 這種方法就是為了解決實例化對象產生大量代碼重復的問題; function createObject(name,age){ // 集中創建函數體; var obj = new Object; // 函數體內創建Object; obj.name = name; obj.age = age; obj.run = function(){ return this.name+this.age+"運行中..."; }; return obj; } var box1 = createObject("lee",100); // 實例化;調用函數並傳參; var box2 = createObject("jack",200); // 實例二; console.log(box1.run()+box2.run()); // 實例保持相對獨立; // 缺點:對象與實例的識別問題;無法搞清楚它們到底是那個對象的實例; console.log(typeof box1); // Object;3.構造函數創建對象
1 2 3 4 5 6 7 8 9 10 11 12 // ECMAScript采用構造函數(構造方法)可用來創建特定的對象; function Box(name,age){ // 構造函數模式; this.name = name; // this代表對象Box; this.age = age; this.run = function(){ return this.name+this.age+"運行中..."; }; } var box1 = new Box("lee",100); // 要創建對象的實例必須用new操作符; var box2 = new Box("jack",200); // box1和box2都是Box對象的實例; console.log(box1 instanceof Box); // true;很清晰的識別box1從屬於Box; // 使用構造函數,即解決了重復實例化的問題,有解決了對象識別的問題;使用構造函數與工廠模式不同之處:
(1).構造函數方法沒有顯示的創建對象(new Object);
(2).直接將屬性和方法賦值給this對象;
(3).沒有return語句;1 // 構造函數規范:
(1).函數名(function Box)和實例化構造名(new Box)相同且大寫;
(2).通過構造函數創建實例對象,必須使用new運算符;
構造函數的問題:
使用構造函數創建每個實例的時候,構造函數裡的方法都要在每個實例上重新創建一遍;
因為ECMAScript中的函數是對象,因此每定義一個函數,也就是實例化了一個對象;
以這種方式創建函數,會導致不同的作用域鏈和標識符解析;
二 原型
// 我們創建的每個函數都有一個prototype(原型)屬性,這個屬性是一個對象;
// 用途:包含可以由特定類型的所有實例共享的屬性和方法;
// 理解:prototype是通過調用構造函數創建的那個對象的原型對象;
// 使用原型的好處是可以讓所有對象實例共享它所包含的屬性和方法;
// 也就是說,不必在構造函數中定義對象信息(屬性/方法),而是可以直接將這些信息添加到原型中;
1.原型模式(prototype添加屬性和方法)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 1.原型模式 function Box(){} // 聲明構造函數; Box.prototype.name = 'Lee'; // 在原型裡添加屬性和方法; Box.prototype.age = 100; Box.prototype.run = function() { return this.name+this.age+'運行中...'; }; var box1 = new Box(); var box2 = new Box(); console.log(box1.run==box2.run); // =>true;方法引用的地址保持一致; // 在原型中多了兩個屬性,這兩個原型屬性都是創建對象時自動生成的; // 1.__proto__:構造函數指向原型對象的一個指針;它的作用:指向構造函數的原型的屬性constructor; 14// IE浏覽器在腳本訪問__proto__會不能識別; 15 // 判斷一個實例對象是否指向了該構造函數的原型對象,可以使用isPrototypeOf()方法來測試; console.log(Box.prototype.isPrototypeOf(box)); // =>true; 只要實例化對象,即都會指向; // 原型模式的執行流程: // 1.先查找構造函數對象的實例裡的屬性或方法,若有,立刻返回; // 2.若構造函數對象的實例裡沒有,則去它的原型對象裡找,若有,就返回; // 雖然我們可以通過對象實例訪問保存在原型中的值,但卻不能訪問通過對象實例重寫原型中的值; var box1 = new Box(); console.log(box1.name); // Lee; 原型裡的值; bo1.name = 'jack'; console.log(box1.name); // Jack;實例自己賦的值; var box2 = new Box(); console.log(box2.name); // Lee;原型裡的值;沒有被box1修改; // 如果想要box1繼續訪問原型裡的值,可以把構造函數裡的屬性刪除即可; delete box1.name; // 刪除實例自己的屬性; console.log(box1.name); // Lee; 原型裡原來的值;2.原型與in操作符
如何判斷屬性是在構造函數的實例裡,還是在原型裡? 可以用hasOwnProperty()函數來驗證;
console.log(box.hasOwnProperty('name')); // 實例裡若有返回true,否則返回false;
in操作符會在通過對象能夠訪問給定屬性時返回true,無論該屬性存在與實例中還是原型中;
console.log('name' in box); // =>true,存在實例中或原型中;3.更簡單的原型語法(原型+字面量模式)
3.更簡單的原型語法(原型+字面量模式)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17