面向?qū)ο蟮?JavaScript
對象(Object)是組成 JavaScript 的基本單元,事實上,JavaScript 中一切都是對象
JavaScript 語言中最重要的幾個部分:引用(reference),作用域(scope),閉包(closure)以及上下文(context)
引用(reference)
引用(reference)的概念是 JavaScript 的基礎(chǔ)之一,"引用"是一個指向?qū)ο髮嶋H位置的指針,但是有一個前提:實際的對象肯定不會是引用(字符串永遠是字符串,數(shù)組永遠是數(shù)組),不過多個變量卻能夠指向同一對象
此外,對象可以包含一系列屬性(property),這些屬性也都不過是到其他對象(比如字符串,數(shù)字,數(shù)組等等)的引用,如果多個變量指向的是同一個對象,那該對象的類型一改變,所有這些變量也會跟著相應(yīng)改變
多個變量引用同一個對象
var obj = new Object();
// objRef 現(xiàn)在是另外一個對象的引用
var objRef = obj;
// 修改原對象的一個屬性
obj.oneProperty = true;
// 這個改變在兩個變量中都反映了出來(因為它們引用的是同一個對象)
console.log( obj.oneProperty === objRef.oneProperty ) // true
自修改對象的例子
var items = ["one", "two", "three"];
// 數(shù)組的一個引用
var itemsRef = items;
items.push("four");
// 這兩個數(shù)組指向同一個數(shù)組對象,所以,它們的長度是一致的
console.log( items.length == itemsRef.length ); // true
需要記住的是,引用指向的只能是具體的對象,而不是另一個引用(JavaScript里的結(jié)果是沿著引用鏈一直上溯到原來那個對象)
修改對象的引用,同時保持完整性
var items = ["one", "two", "three"];
var itemsRef = items;
items = ["four"];
// items 和 itemsRef 現(xiàn)在指向不同的對象
// items 指向的是 ["four"] 這個數(shù)組
// itemsRef 指向的是 ["one", "two", "three"] 這個數(shù)組
console.log( items != itemsRef ) // true
從上面這個例子可以看出,實際對象已經(jīng)改變了,但是原來指向它的引用仍然保持指向舊的對象
我們再來看下面這個特殊的例子,看上去像是自修改對象,但是其結(jié)果卻產(chǎn)生了一個新的非引用對象
在執(zhí)行字符串連接操作的時候,結(jié)果總是會一個新的字符串對象,而非原字符串的修改版本
var item = "test";
var itemRef = item;
// 這會創(chuàng)建一個新的對象,而非修改原對象
item += "ing";
// 不相等,因為新的字符串對象已經(jīng)被創(chuàng)建
console.log( item != itemRef ) // true
函數(shù)重載和類型檢查
函數(shù)重載(function overloading)
函數(shù)重載(function overloading)必須依賴兩件事情:判斷傳入?yún)?shù)的數(shù)量的能力和判斷傳入?yún)?shù)類型的能力
JavaScript 的每個函數(shù)都帶有一個僅在這個函數(shù)范圍內(nèi)作用的變量(contextual variable)稱為參數(shù)(argument),它是一個包含所有傳給函數(shù)的參數(shù)的偽數(shù)組(pseudo-array)
函數(shù)重載的兩個例子
// 實例一
function sendMsg(msg, obj) {
if (arguments.length == 2) {
obj.handleMsg(msg);
} else {
console.log(msg);
}
}
// 僅提供一個參數(shù)
sendMsg("hello world!");
// 兩個參數(shù)
sendMsg("hello", {
handleMsg: function (msg) {
console.log(msg)
}
})
// 實例二
function makeArray() {
var arr = [];
// 遍歷傳入的每個參數(shù)
for (var i = 0; i < arguments.length; i++) {
arr.push(arguments[i]);
}
return arr;
}
類型檢查
這里只討論兩種比較有用的方法
第一種方法是使用顯而易見的 typeof 操作符。
這個工具提供了一個字符串名稱(string name),用于表達內(nèi)容的類型,當(dāng)變量不是 object 或者 array 類型的時候,這應(yīng)該算是最完美的解決方法了,但是對于自定義的對象,比如 obj 就不能用這個方法了,因為它只會返回 object
使用 typeof 來判斷對象類型
// 檢查 num 是否實際上是字符串
if (typeof num == "string") {
// 如果是,則轉(zhuǎn)為整數(shù)
num = parseInt(num)
}
// 檢查 arr 是否實際上是字符串
if (typeof arr == "string") {
// 如果是,則根據(jù) "," 切分為數(shù)組
arr = arr.split(",")
}
第二種檢查對象類型的方法,需要引用所有 JavaScript 對象都帶有的一個的屬性,稱為構(gòu)造函數(shù)(constructor),這一屬性引用的是原本用來構(gòu)造該對象的那個函數(shù)
使用構(gòu)造函數(shù)屬性來判斷對象的類型
// 檢查 num 是否實際上是字符串
if (num.constructor == String) {
// 如果是,則轉(zhuǎn)為整數(shù)
num = parseInt(num)
}
// 檢查 arr 是否實際上是字符串
if (arr.constructor == Array) {
// 如果是,則根據(jù) "," 切分為數(shù)組
arr = arr.split(",")
}
作用域
待續(xù)...