萬盛學電腦網

 萬盛學電腦網 >> 腳本專題 >> javascript >> JavaScript 面向對象與原型

JavaScript 面向對象與原型

 ECMAScript有兩種開發模式:1.函數式(過程化);2.面向對象(OOP);

一 創建對象
1.普通的創建對象

1 2 3 4 5 6 7 8 9 // 創建一個對象,然後給這個對象新的屬性和方法; var box = new Object(); // 創建一個Object對象; box.name = 'lee'; // 創建一個name屬性並賦值; box.age = 100; box.run = function(){ // 創建一個run()方法並返回值; return this.name+this.age+'運行中...'; } console.log(box.run()); // 輸入屬性和方法的值; // 缺點:想創建類似的對象,就會產生大量的代碼;

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運算符;

1 2 3 4 5 6 7 // 構造函數和普通函數的區別: var box = new Box('lee',100); // 構造模式調用; Box('lee',200); // 普通模式調用,無效;   var o = new Object(); Box.call(o,'jack',200); // 對象冒充調用; // 將Box對象作用域擴充到對象o;Box()方法的運行環境已經變成了對象o裡;

構造函數的問題:
使用構造函數創建每個實例的時候,構造函數裡的方法都要在每個實例上重新創建一遍;
因為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; 原型裡原來的值;

JavaScript 面向對象與原型 三聯

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
copyright © 萬盛學電腦網 all rights reserved