node.js學習之路(一)之“面向對象的JavaScript入門”

一、前言

node.js以JavaScript爲基礎,因此學習node.js之前有必要複習一下JavaScript,其中我的學習之路是先看《JavaScript高級程序設計》,後看《JavaScript語言精粹》,準備再繼續看《webkit技術內幕》。

其中JavaScript面向對象的特性在node.js裏是必須熟練掌握和深刻理解的知識點,因此特地提出來一起復習。


二、JavaScript面向對象入門

JavaScript創建對象有兩種方式:
1.Literal Notation
2.Constructor Notation

1.Literal Notation方式介紹

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 :)

很好,我們傳入了一個參數(noise),並且在方法的內部訪問了它。下面我們繼續添加一個方法來訪問name屬性:

bill.sayName = function() {
    console.log( "Hello " + this.name );
};
bill.sayName(); // "Hello Bill E Goat"

我們可以通過this.propertyName在一個方法內部訪問屬性

bill.sayName; // function

這些代碼會有什麼結果。我們不使用括號調用sayName,它返回了一個方法定義。繼續探索!

var sound = bill.sound;
sound('moo!'); // "moo!"

我們把一個叫sound的本地方法賦值給一個對象sound,現在可以在sound後面添加括號並傳入參數調用那個方法了。如果我們試着克隆Bill會有什麼結果?

var sally = bill;
sally.name; // "Bill E Goat", But her name is Sally silly
sally.name = "Sally";
sally.name; // "Sally", Better
bill.name; // "Sally", Oh no what happened to Bill

在上面的例子中我們創建了一個新的變量sally,並讓它和bill相等。現在sally和bill在內存中引用同樣的對象。對一個對象的改變會影響到另一個。

下面再看另外一個例子:

bill.name = "Bill E Goat";
bill.sayName(); // "Hello Bill E Goat";
var sayName = bill.sayName;
sayName; // function, OK so far so good
sayName(); // "Hello ", huh why didn't it print out Bills name?

bill的name屬性是一個本地變量,sayName方法是在全局範圍內創建的,所以this.name會在全局範圍內查找name的值。但問題是name沒有定義。讓我們來定義一個全局變量name看看會發生什麼:

var name = "Bearded Octo";
sayName(); // "Hello Bearded Octo"

在這裏我們創建了一個全局變量name,並賦值“Bearded Octo”。當我們調用sayName方法時它在全局範圍內查找name並訪問到了值“Bearded Octo”,很好。下面看看Constructor Notation。


2.Constructor Notation方式介紹

Constructor Notation是另外一種寫面向對象JavaScript的方法。當你需要爲一個對象設置初始屬性值和方法或者打算創建一個對象的不同實例但他們的屬性和方法都是不同的,這時首選Constructor Notation方式。下面從創建一個空對象開始:

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 (typeof title !== 'undefined') { 
    this.title = title; 
} else { 
    this.title = ""; 
} 
// Is the same as 
this.title = typeof title !== 'undefined' ? 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"

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章