萬盛學電腦網

 萬盛學電腦網 >> 腳本專題 >> javascript >> 如何快速掌握JavaScript面向對象編程

如何快速掌握JavaScript面向對象編程

  導讀:經常看到一些JavaScript的代碼髒亂得無法理解,到處都是屬性和方法,或者一個循環套著一個循環。但如果使用面向對象就能很好的理清代碼,並方便理解和修改代碼。如果你不希望自己的代碼只有上帝理解的話,就請盡量考慮使用面向對象的模式。


譯文正文:


到處都是屬性、方法,代碼極其難懂,天哪,我的程序員,你究竟在做什麼?仔細看看這篇指南,讓我們一起寫出優雅的面向對象的JavaScript代碼吧!


作為一個開發者,能否寫出優雅的代碼對於你的職業生涯至關重要。隨著像Node.js這類技術的發展,你甚至可以在服務器端使用JavaScript了。同樣的,你也可以使用JavaScript來控制MongoDB的持續數據存儲。


文本標記


文本標記只是JavaScript裡創建對象的一種方法,當然這裡肯定不止這一種,但它是你在只打算創建一個對象實例時的首選方法。


var bill = {};


上面的代碼並不實用,它只是一個空對象。接下來我們動態地向這個對象中添加一些屬性和方法。


bill.name = “Bill E Goat”;


bill.sound = function() {


console.log( 'bahhh!' );


};


這裡添加了屬性name,並且給它分配了值“Bill E Goat”。我們並不需要先創建一個空對象,而可以把所有代碼直接寫在一對括號裡。


var bill = {


name: “Bill E Goat”,


sound: function() {


console.log( 'bahhh!' );


}


};


是不是很美觀?訪問它的屬性和方法就像呼吸一樣簡單、自然。


bill.name; // “Bill E Goat”


bill.sound(); // “bahhh”


如果屬性名不是一個合法的標志符,我們還可以這樣訪問它:


bill['name']; // “Bill E Goat”


注意:我在調用方法時在其後添加了圓括號。現在,我們再重寫一下當前的sound方法,並添加一個參數。

  bill.sound = function(noise) {


console.log(noise);


};


bill.sound(“brrr!”); // “brrr!” He's cold :)


很好,我們已經傳入參數了,並且在方法定義中訪問了它。接下來,向對象中增加一個新方法來訪問name屬性。


bill.sayName = function() {


console.log( “Hello “ + this.name );


};


bill.sayName(); // “Hello Bill E Goat”


我們可以使用this.propertyName(在本例中即this.name)在方法內訪問屬性。


bill.sayName; // function


怎麼回事?訪問sayName方法返回了一個方法定義。現在讓我們再深入些。


var sound = bill.sound;


sound('moo!'); // “moo!”


現在我們指定了sound方法為一個局部函數,可以調用這個函數並且傳遞參數。你認為在復制bill的時候會發生什麼?(類比下克隆羊Dolly)


var sally = bill;


sally.name; // “Bill E Goat”,可它的名字是Sally


sally.name = “Sally”;


sally.name; // “Sally”,好些了


bill.name; // “Sally”,問題又轉移到bill身上了


上面的例子中我們新建了一個變量sally,並使它和bill相同,所以bill和sally會在內存中引用了同一個對象。這時候給改變一塊它們就會同時發生改變。再看看下面這段代碼:


bill.name = “Bill E Goat”;


bill.sayName(); // “Hello Bill E Goat”;


var sayName = bill.sayName;


sayName; // function 目前為止一切順利


sayName(); // “Hello “,為什麼這裡又不再顯示bill的名字了?


bill的name是一個本地實例變量,只對bill可得。當sayName方法被創建為全局變量時,當它碰到this.name聲明時,它會在全局查找name的值。唯一的問題在於name還沒有被定義。現在讓我們在全局定義name,看看會發生什麼:


var name = “Bearded Octo”;


sayName(); // “Hello Bearded Octo”


這裡我們在全局范圍內定義了name變量,並且賦予了值“Bearded Octo”。當我們在調用sayHello方法時它會在全局范圍內查找name變量,最終會獲得值“Bearded Octo”。我們為什麼不為這幾個對象建立一個共同的“類”呢?

  構造函數


構造函數是另一個編寫面向對象JavaScript代碼的方法,當你需要初始化對象的屬性、方法,或者需要創建多個屬性、方法各不相同的實例時,它將是你最佳的選擇。同樣我們先從創建一個空對象開始:


function Game() {};


這個對象包括自己的屬性,你甚至可以在創建對象時傳入屬性,然後再對其進行修改。


var zelda = new Game();


var smb = new Game();


zelda.title = “Legend of Zelda”;


smb.title = “Super Mario Brothers”;


zelda.title; // “Legend of Zelda”


smb.title; // “Super Mario Brothers”


現在這個對象已經有自己的方法了!新創建對象時我們甚至可以傳遞屬性,之後再修改。


function Game(title) {


this.title = typeof title !== 'undefined' ? title : ““;


};


var zelda = new Game(”Legend of Zelda“);


zelda.title; // “Legend of Zelda”


zelda.title = “Ocarina of Time”;


zelda.title; // “Ocarina of Time”


var blank = new Game();


blank.title; // ““


也許你沒看明白第二行的內容,其實是使用了三元操作來避免單行的if else,它和下面標准的if else語句是一個意思。


if (typeof title !== 'undefined') {


this.title = title;


} else {


this.title = ““;


}


// Is the same as


this.title = typeof title !== 'undefined' ? title : ““;


如果title變量在對象被創建時傳入,title實例變量將會指定為title的值。如果沒有值傳入,那麼title將會被初始化為默認值。我們同樣可以創建一個方法來訪問這個屬性:


zelda.loveTitle = function() {


console.log( “I love “ + this.title );


};


zelda.loveTitle(); // “I love Ocarina of Time”


這樣就很整潔了,但是我們還能做得更好。我們可以在Game類中添加一個方法,這樣所有Game類的實例將都能使用此方法。


Game.prototype.heartIt = function() {


console.log( “I heart “ + this.title );


};


zelda.heartIt(); // “I heart Ocarina of Time”


smb.heartIt(); // “I heart Super Mario Brothers”

 

copyright © 萬盛學電腦網 all rights reserved