javascript高級程序設計 學習筆記 第五章 上

?
第五章
?
引用類型的值(對象)是引用類型的一個實例。在 ECMAScript 中,引用類型是一種數據結構, 用于將數據和功能組織在一起。它也常被稱為類,但這種稱呼并不妥當。盡管 ECMAScript 從技術上講是一門面向對象的語言,但它不具備傳統的面向對象語言所支持的類和接口等基本結構。引用類型有時候也被稱為對象定義,因為它們描述的是一類對象所具有的屬性和方法。
?
對象是某個特定引用類型的實例。新對象是使用 new 操作符后跟一個構造函數來創建的。 構造函數本身就是一個函數,只不過該函數是出于創建新對象的目的而定義的。
?
ECMAScript 提供了很多原生引用類 型(例如 Object),以便開發人員用以實現常見的計算任務。
?
5.1 Object類型
到目前為止,我們看到的大多數引用類型值都是 Object 類型的實例;而且,Object 也是 ECMAScript 中使用最多的一個類型。
創建 Object 實例的方式有兩種。第一種是使用 new 操作符后跟 Object 構造函數。
eg:
var person = new Object(); 
person.name = "Nicholas"; 
person.age = 29; 
另一種方式是使用對象字面量表示法。對象字面量是對象定義的一種簡寫形式,目的在于簡化創建 包含大量屬性的對象的過程。
eg:
var person = { name : "Nicholas", age : 29 
};
在最后一個屬性后面添加逗號,會在 IE7 及更早版本和Opera 中導致錯誤。
?
在這個例子中,左邊的花括號({)表示對象字面量的開始,因為它出現在了表達式上下文 (expression context)中。ECMAScript 中的表達式上下文指的是能夠返回一個值(表達式)。賦值操作 符表示后面是一個值,所以左花括號在這里表示一個表達式的開始。同樣的花括號,如果出現在一個語句上下文(statement context)中,例如跟在 if 語句條件的后面,則表示一個語句塊的開始。
?
在使用對象字面量語法時,屬性名也可以使用字符串。
eg:
var person = {"name" : "Nicholas", "age" : 29, 5 : true 
};
這個例子會創建一個對象,包含三個屬性:name、age 和 5。但這里的數值屬性名會自動轉換為字符串。
?
對象字面量也是向函數傳遞大量可選參 數的首選方式。
eg:
?
這種傳遞參數的模式最適合需要向函數傳入大量可選參數的情形。一般來講,命名參數雖然容易處理,但在有多個可選參數的情況下就會顯示不夠靈活。最好的做法 是對那些必需值使用命名參數,而使用對象字面量來封裝多個可選參數。
?
一般來說,訪問對象屬性時使用的都是點表示法,這也是很多面向對象語言中通用的語法。不過, 在 JavaScript 也可以使用方括號表示法來訪問對象的屬性。在使用方括號語法時,應該將要訪問的屬性 以字符串的形式放在方括號中。
eg:
alert(person["name"]); //"Nicholas"
alert(person.name); //"Nicholas"
從功能上看,這兩種訪問對象屬性的方法沒有任何區別。但方括號語法的主要優點是可以通過變量 來訪問屬性。
eg:
var propertyName = "name";
alert(person[propertyName]); //"Nicholas"
如果屬性名中包含會導致語法錯誤的字符,或者屬性名使用的是關鍵字或保留字,也可以使用方括 號表示法。
eg:
person["first name"] = "Nicholas"; 
由于"first name"中包含一個空格,所以不能使用點表示法來訪問它。然而,屬性名中是可以包 含非字母非數字的,這時候就可以使用方括號表示法來訪問它們。
?
通常,除非必須使用變量來訪問屬性,否則我們建議使用點表示法。
?
5.2 Array類型
數據的有序列表,但與其他語言不同的是,ECMAScript 數組的每一項可以保存任何類型的數據。而且,ECMAScript 數組的大小是可以動態調整的,即可以隨著數據的添加自動增長以容 納新增數據。
?
創建數組的基本方式有兩種。第一種是使用 Array構造函數。
eg:
var colors = new Array(); 
如果預先知道數組要保存的項目數量,也可以給構造函數傳遞該數量,而該數量會自動變成 length 屬性的值。
eg:
var colors = new Array(20);
也可以向 Array 構造函數傳遞數組中應該包含的項。以下代碼創建了一個包含 3 個字符串值的數組:
var colors = new Array("red", "blue", "green");
給構造函數傳遞值:如果傳遞的是數 值,則會按照該數值創建包含給定項數的數組;而如果傳遞的是其他類型的參數,則會創建包含那個值 的只有一項的數組。
?
另外,在使用 Array 構造函數時也可以省略 new 操作符。如下面的例子所示,省略 new 操作符的 結果相同:
var colors = Array(3); // 創建一個包含 3 項的數組
var names = Array("Greg"); // 創建一個包含 1 項,即字符串"Greg"的數組 
創建數組的第二種基本方式是使用數組字面量表示法。數組字面量由一對包含數組項的方括號表 示,多個數組項之間以逗號隔開。
var colors = ["red", "blue", "green"]; // 創建一個包含 3 個字符串的數組
var names = []; // 創建一個空數組 
var values = [1,2,]; // 不要這樣!這樣會創建一個包含 2 或 3 項的數組 
var options = [,,,,,]; // 不要這樣!這樣會創建一個包含 5 或 6 項的數組
分析:
在 IE 中,values 會成為一個包含 3 個項且每 項的值分別為 1、2 和 undefined 的數組;在其他瀏覽器中,values 會成為一個包含 2 項且值分別為 1 和 2 的數組。原因是 IE8 及之前版本中的 ECMAScript 實現在數組字面量方面存在 bug。由于這個 bug導致的另一種情況如最后一行代碼所示,該行代碼可能會創建包含 5 項的數組(在 IE9+、Firefox、Opera、Safari 和 Chrome 中),也可能會創建包含 6 項的數組(在 IE8 及更早版本中)。在像這種省略值的情況下, 每一項都將獲得undefined值;這個結果與調用Array構造函數時傳遞項數在邏輯上是相同的。但是 由于 IE 的實現與其他瀏覽器不一致,因此我們強烈建議不要使用這種語法。
?
在讀取和設置數組的值時,要使用方括號并提供相應值的基于 0 的數字索引,如下所示: var colors = ["red", "blue", "green"]; // 定義一個字符串數組
alert(colors[0]); // 顯示第一項 colors[2] = "black"; // 修改第三項 colors[3] = "brown"; // 新增第四項
如果設 置某個值的索引超過了數組現有項數,如這個例子中的 colors[3]所示,數組就會自動增加到該索引 值加 1 的長度(就這個例子而言,索引是 3,因此數組長度就是 4)。
?
數組的 length 屬性很有特點——它不是只讀的。因此,通過設置這個屬性,可以從數組的末尾移 除項或向數組中添加新項。請看下面的例子:
var colors = ["red", "blue", "green"]; // 創建一個包含 3 個字符串的數組 
colors.length = 2;
alert(colors[2]); //undefined
如果將其 length屬性設置為大于數組 項數的值,則新增的每一項都會取得 undefined 值,如下所示:
var colors = ["red", "blue", "green"]; // 創建一個包含 3 個字符串的數組 
colors.length = 4;
alert(colors[3]); //undefined
利用 length 屬性也可以方便地在數組末尾添加新項,如下所示:
var colors = ["red", "blue", "green"]; // 創建一個包含 3 個字符串的數組 
colors[colors.length] = "black";  //(在位置3)添加一種顏色 
colors[colors.length] = "brown"; //(在位置4)再添加一種顏色
數組最多可以包含 4 294 967 295 個項.
5.2.1 檢測數組
對于一個網頁,或者一個全局作用域而言,使用 instanceof 操作符就能得到滿意的結果:
if (value instanceof Array){ 
//對數組執行某些操作
}
instanceof 操作符的問題在于,它假定只有一個全局執行環境。如果網頁中包含多個框架,那實 際上就存在兩個以上不同的全局執行環境,從而存在兩個以上不同版本的 Array構造函數。如果你從 一個框架向另一個框架傳入一個數組,那么傳入的數組與在第二個框架中原生創建的數組分別具有各自 不同的構造函數。
?
為了解決這個問題,ECMAScript 5 新增了 Array.isArray()方法。這個方法的目的是最終確定某 個值到底是不是數組,而不管它是在哪個全局執行環境中創建的。這個方法的用法如下。
if (Array.isArray(value)){ 
//對數組執行某些操作
}
支持 Array.isArray()方法的瀏覽器有 IE9+、Firefox 4+、Safari 5+、Opera 10.5+和 Chrome。
5.2.2 轉換方法
所有對象都具有 toLocaleString()、toString()和 valueOf()方法。其中,調用 數組的 toString()方法會返回由數組中每個值的字符串形式拼接而成的一個以逗號分隔的字符串。而 調用 valueOf()返回的還是數組。實際上,為了創建這個字符串會調用數組每一項的 toString()方 法。
?
當調用數組的 toLocaleString()方法時,它也會創建一個數組值的以逗號分隔的字符 串。而與前兩個方法唯一的不同之處在于,這一次為了取得每一項的值,調用的是每一項的 toLocale- String()方法,而不是 toString()方法。
eg:
var person1 = { toLocaleString : function () { return "Nikolaos"; }, toString : function() { return "Nicho"; 
} };
var person2 = { toLocaleString : function () { return "Grigorios"; }, toString : function() { return "Greg"; 
} };
var people = [person1, person2];
alert(people); //Nicho,Greg 
alert(people.toString()); //Nicho,Greg 
alert(people.toLocaleString()); //Nikolaos,Grigorios
數組繼承的 toLocaleString()、toString()和 valueOf()方法,在默認情況下都會以逗號分隔的字 符串的形式返回數組項。而如果使用 join()方法,則可以使用不同的分隔符來構建這個字符串。join()方 法只接收一個參數,即用作分隔符的字符串,然后返回包含所有數組項的字符串。
eg:
var colors = [1, "green", "blue"];colors.join("||"); // "1||green||blue"
我們使用 join()方法重現了 toString()方法的輸出。在傳遞逗號的情況下,得到了以 逗號分隔的數組值。
var colors = [1, "green", "blue"];
colors.toString(); //"1,green,blue"
//colors.join(",") //"1,green,blue" 
如果不給 join()方法傳入任何值,或者給它傳入 undefined,則使用逗號作為分隔 符。IE7 及更早版本會錯誤的使用字符串"undefined"作為分隔符。
eg:
var colors = [1, "blue","red"];//colors.join() //"1,blue,red"
//colors.join("undefined") //"1undefinedblueundefinedred"
colors.join(undefined) //"1,blue,red"
//colors.join(null) //"1nullbluenullred"
如果數組中的某一項的值是 null 或者 undefined,那么該值在 join()、 toLocaleString()、toString()和 valueOf()方法返回的結果中以空字符串表示。
eg:
var colors = [1, undefined, "blue",null];//colors.join(",") //"1,,blue,"
//colors.toString() //"1,,blue,"
colors.valueOf() //[1, undefined, "blue", null]
//colors.toLocaleString() //"1,,blue,"
colors.valueOf()結果并未預想的以空字符串表示???
eg:
var nobody = [1,,"red"];
var color = [1,2,"red"];
var nullArr = [1,null,"red"];
var undefinedArr = [1,undefined,"red"];//nobody.valueOf() //[1, undefined, "red"]
//nobody.join(",") //"1,,red"
//nobody.toString() //"1,,red"
//nobody instanceof Array //true//color.valueOf() //[1, 2, "red"]
//color.join(",") //"1,2,red"
//color.toString() //"1,2,red"
//color instanceof Array //true//nullArr.valueOf() //[1, null, "red"]
//nullArr.join(",") //"1,,red"
//nullArr.toString() //"1,,red"
//nullArr instanceof Array //true//undefinedArr.valueOf() //[1, undefined, "red"]
//undefinedArr.join(",") //"1,,red"
undefinedArr.toString() //"1,,red"
//undefinedArr instanceof Array //true
分析:當數組某一項為空時,valueOf結果為undefined,其他情況都返回原來值(null的valueOf結果為null,undefined的valueOf結果為undefined);
而當數組某項為空或null或nudefined:join(",")和toString()的結果都為空。
5.2.3 棧方法
棧是一種 LIFO(Last-In-First-Out, 后進先出)的數據結構,也就是最新添加的項最早被移除。而棧中項的插入(叫做推入)和移除(叫做 彈出),只發生在一個位置——棧的頂部。ECMAScript 為數組專門提供了 push()和 pop()方法,以便 實現類似棧的行為。
?
push()方法可以接收任意數量的參數,把它們逐個添加到數組末尾,并返回修改后數組的長度。而 pop()方法則從數組末尾移除最后一項,減少數組的 length 值,然后返回移除的項。
eg:
var colors = new Array();
var count = colors.push("red", "green");console.log(count); //2
 
count = colors.push("black");console.log(count); //3
console.log(colors); // ["red", "green", "black"]var item = colors.pop();console.log(item); //black
console.log(colors.length); //2
console.log(colors); // ["red", "green"]
5.2.4 隊列方法
隊列數據結構的訪問規則是 FIFO(First-In-First-Out, 先進先出)。隊列在列表的末端添加項,從列表的前端移除項。shift(),它能夠移除數組中的第一個項并返回該項,同時將數組長度減 1。結合使用 shift()和 push()方法,可以像使 用隊列一樣使用數組。
eg:
var colors = new Array();
var count = colors.push("red", "green");console.log(count); //2
 
count = colors.push("black");console.log(count); //3
console.log(colors); // ["red", "green", "black"]var item = colors.shift();console.log(item); //red
console.log(colors.length); //2
console.log(colors); // ["green", "black"]
unshift()與 shift()的用途相反: 它能在數組前端添加任意個項并返回新數組的長度。因此,同時使用 unshift()和 pop()方法,可以從相反的方向來模擬隊列,即在數組的前端添加項,從數組末端移除項。
eg:
var colors = new Array();
var count = colors.unshift("red", "green");console.log(count); //2
 
count = colors.unshift("black");console.log(count); //3
console.log(colors); // ["black", "red", "green"]var item = colors.pop();console.log(item); //green
console.log(colors.length); //2
console.log(colors); // ["black", "red"]
?
?
5.2.5 重排序方法
數組中已經存在兩個可以直接用來重排序的方法:reverse()和 sort()。有讀者可能猜到了,
reverse()方法會反轉數組項的順序。
eg:
var values = [1, 2, 3, 4, 5]; 
values.reverse(); alert(values);
//5,4,3,2,1
在默認情況下,sort()方法按升序排列數組項——即最小的值位于最前面,最大的值排在最后面。 為了實現排序,sort()方法會調用每個數組項的 toString()轉型方法,然后比較得到的字符串,以 確定如何排序。即使數組中的每一項都是數值,sort()方法比較的也是字符串。
eg:
 var values = [0, 1, 5, 10, 15];
values.sort();
alert(values); //0,1,10,15,5
sort()方法也會根據測試字符串的結果改變原來的順序。 因為數值 5 雖然小于 10,但在進行字符串比較時,"10"則位于"5"的前面,于是數組的順序就被修改了。
sort()方法可以接收一個比較函數作為參 數,以便我們指定哪個值位于哪個值的前面。
eg:
 function compare(){return -1;} var values = [0, 10,2,15];values.sort(compare);console.log(values); // [0, 10, 2, 15]
函數返回-1時,順序不變。
eg2:
 function compare(){return 1;} var values = [0, 10,2,15];values.sort(compare);console.log(values); // [15, 2, 10, 0]
函數返回1時,順序相反。
eg3:
 function compare(){return 0;} var values = [0, 10,2,15];values.sort(compare);console.log(values); // [0, 10, 2, 15]
函數返回0時,順序不變。
eg4:
 function compare(value1, value2) {if (value1 < value2) {return -1;} else if (value1 > value2) {return 1;} else {return 0; }} var values = [0, 10,2,15];values.sort(compare);console.log(values); // [0, 2, 10, 15]
在將比較函數傳遞到 sort()方法之后,數值仍然保持了正確的升序。
eg5:
 function compare(value1, value2) {if (value1 < value2) {return 1;} else if (value1 > value2) {return -1;} else {return 0; }} var values = [0, 10,2,15];values.sort(compare);console.log(values); // [15, 10, 2, 0]
通過比較函數產生降序排序的結果,只要交換比較函數返回的值即可。
?
對于數值類型或者其 valueOf()方法會返回數值類型的對象類型,可以使用一個更簡單的比較函數。這個函數只要用第二個值減第一個值即可
 function compare(value1, value2){ return value2 - value1; 
} 
由于比較函數通過返回一個小于零、等于零或大于零的值來影響排序結果,因此減法操作就可以適
當地處理所有這些情況。
?
5.2.6 操作方法
concat()方法可以基于當前數 組中的所有項創建一個新數組。具體來說,這個方法會先創建當前數組一個副本,然后將接收到的參數 添加到這個副本的末尾,最后返回新構建的數組。在沒有給 concat()方法傳遞參數的情況下,它只是 復制當前數組并返回副本。如果傳遞給 concat()方法的是一或多個數組,則該方法會將這些數組中的 每一項都添加到結果數組中。如果傳遞的值不是數組,這些值就會被簡單地添加到結果數組的末尾。
eg:
var colors = ["red", "green", "blue"]; 
var colors2 = colors.concat("yellow", ["black", "brown"]); 
alert(colors); //red,green,blue 
alert(colors2); //red,green,blue,yellow,black,brown ?
slice(),它能夠基于當前數組中的一或多個項創建一個新數組。slice()方法可以 接受一或兩個參數,即要返回項的起始和結束位置。在只有一個參數的情況下,slice()方法返回從該 參數指定位置開始到當前數組末尾的所有項。如果有兩個參數,該方法返回起始和結束位置之間的項— —但不包括結束位置的項。注意,slice()方法不會影響原始數組。
eg:
var colors = ["red", "green", "blue", "yellow", "purple"]; 
var colors2 = colors.slice(1); 
var colors3 = colors.slice(1,4); 
alert(colors2); //green,blue,yellow,purple 
alert(colors3); //green,blue,yellow 
如果 slice()方法的參數中有一個負數,則用數組長度加上該數來確定相應的位 置。例如,在一個包含 5 項的數組上調用 slice(-2,-1)與調用 slice(3,4)得到的 結果相同。如果結束位置小于起始位置,則返回空數組。
?
splice()方法,這個方法恐怕要算是最強大的數組方法了,它有很多種用法。 splice()的主要用途是向數組的中部插入項,但使用這種方法的方式則有如下 3 種。
  • 刪除:可以刪除任意數量的項,只需指定 2 個參數:要刪除的第一項的位置和要刪除的項數。 例如,splice(0,2)會刪除數組中的前兩項。
  • 插入:可以向指定位置插入任意數量的項,只需提供 3 個參數:起始位置、0(要刪除的項數) 和要插入的項。如果要插入多個項,可以再傳入第四、第五,以至任意多個項。例如, splice(2,0,"red","green")會從當前數組的位置 2 開始插入字符串"red"和"green"。
  • 替換:可以向指定位置插入任意數量的項,且同時刪除任意數量的項,只需指定 3 個參數:起 始位置、要刪除的項數和要插入的任意數量的項。插入的項數不必與刪除的項數相等。例如, splice (2,1,"red","green")會刪除當前數組位置 2 的項,然后再從位置 2 開始插入字符串 "red"和"green"。
  • splice()方法始終都會返回一個數組,該數組中包含從原始數組中刪除的項(如果沒有刪除任何 項,則返回一個空數組)。
eg:?
var colors = ["red", "green", "blue"];//var removed = colors.splice(0,1); 
//console.log(colors); // ["green", "blue"] 
//console.log(removed); // ["red"],返回的數組中只包含一項var removed = colors.splice(1, 0, "yellow", "orange"); 
console.log(colors); // ["red", "yellow", "orange", "green", "blue"]
console.log(removed); // [],返回的是一個空數組//var removed = colors.splice(1, 1, "red", "purple");
//console.log(colors); // ["red", "red", "purple", "blue"]
//console.log(removed); // ["green"],返回的數組中只包含一項
5.2.7 位置方法
ECMAScript 5 為數組實例添加了兩個位置方法:indexOf()和 lastIndexOf()。這兩個方法都接收 兩個參數:要查找的項和(可選的)表示查找起點位置的索引。其中,indexOf()方法從數組的開頭(位 置 0)開始向后查找,lastIndexOf()方法則從數組的末尾開始向前查找。
這兩個方法都返回要查找的項在數組中的位置,或者在沒找到的情況下返回?1。在比較第一個參數與數組中的每一項時,會使用全等操作符;也就是說,要求查找的項必須嚴格相等(就像使用===一樣)。
eg1:
var numbers = [1,2,3,4,5,4,3,2,1];console.log(numbers.indexOf(4)); //3
console.log(numbers.lastIndexOf(4)); //5
console.log(numbers.indexOf(4, 4)); //5
console.log(numbers.lastIndexOf(4, 4)); //3
console.log(numbers.indexOf("4")); //-1
eg2:
var person = { name: "Nicholas" };
var morePeople = [person];
var people = [{ name: "Nicholas" }];console.log(people); // [Object { name="Nicholas"}]
console.log(morePeople); //[Object { name="Nicholas"}]
console.log(people==morePeople); //false ????
console.log(people.indexOf(person)); //-1 ???
console.log(morePeople.indexOf(person)); //0
為什么people==morePeople結果為false??? 數組是對象,不能直接比較的。
使用 indexOf()和 lastIndexOf()方法查找特定項在數組中的位置非常簡單,支持它們的瀏覽器包 括 IE9+、Firefox 2+、Safari 3+、Opera 9.5+和 Chrome。
?
5.2.8 迭代方法
?
ECMAScript 5 為數組定義了 5 個迭代方法。每個方法都接收兩個參數:要在每一項上運行的函數和 (可選的)運行該函數的作用域對象——影響 this 的值。傳入這些方法中的函數會接收三個參數:數 組項的值、該項在數組中的位置和數組對象本身。根據使用的方法不同,這個函數執行后的返回值可能
會也可能不會影響方法的返回值。以下是這 5 個迭代方法的作用。
  • every():對數組中的每一項運行給定函數,如果該函數對每一項都返回 true,則返回 true。
  • filter():對數組中的每一項運行給定函數,返回該函數會返回 true 的項組成的數組。
  • forEach():對數組中的每一項運行給定函數。這個方法沒有返回值。
  • map():對數組中的每一項運行給定函數,返回每次函數調用的結果組成的數組。
  • some():對數組中的每一項運行給定函數,如果該函數對任一項返回 true,則返回 true。
以上方法都不會修改數組中的包含的值。
在這些方法中,最相似的是 every()和 some(),它們都用于查詢數組中的項是否滿足某個條件。
對 every()來說,傳入的函數必須對每一項都返回 true,這個方法才返回 true;否則,它就返回
false。而 some()方法則是只要傳入的函數對數組中的某一項返回 true,就會返回 true。
eg:
var numbers = [1,2,3,4,5,4,3,2,1];var everyResult = numbers.every(function(item, index, array){return (item > 2);});
console.log(everyResult); //falsevar someResult = numbers.some(function(item, index, array){return (item > 2);});
console.log(someResult); //truevar filterResult = numbers.filter(function(item, index, array){return (item > 2);});
console.log(filterResult); // [3, 4, 5, 4, 3]var mapResult = numbers.map(function(item, index, array){return item * 2;});
console.log(mapResult); // [2, 4, 6, 8, 10, 8, 6, 4, 2]
filter()方法對查詢符合某些條件的所有數組項非常有用。
map()也返回一個數組,而這個數組的每一項都是在原始數組中的對應項上運行傳入函數的結果。這個方法適合創建包含的項與另一個數組 一一對應的數組。
?
最后一個方法是 forEach(),它只是對數組中的每一項運行傳入的函數。這個方法沒有返回值, 本質上與使用 for 循環迭代數組一樣。
eg:
var numbers = [1,2,3,4,5,4,3,2,1]; 
numbers.forEach(function(item, index, array){
//執行某些操作 
});
這些數組方法通過執行不同的操作,可以大大方便處理數組的任務。支持這些迭代方法的瀏覽器有 IE9+、Firefox 2+、Safari 3+、Opera 9.5+和 Chrome。
?
5.2.9 歸并方法
?
ECMAScript 5 還新增了兩個歸并數組的方法:reduce()和 reduceRight()。這兩個方法都會迭代數組的所有項,然后構建一個最終返回的值。其中,reduce()方法從數組的第一項開始,逐個遍歷 到最后。而 reduceRight()則從數組的最后一項開始,向前遍歷到第一項。
這兩個方法都接收兩個參數:一個在每一項上調用的函數和(可選的)作為歸并基礎的初始值。傳給 reduce()和 reduceRight()的函數接收 4 個參數:前一個值、當前值、項的索引和數組對象。這 個函數返回的任何值都會作為第一個參數自動傳給下一項。第一次迭代發生在數組的第二項上,因此第 一個參數是數組的第一項,第二個參數就是數組的第二項。
使用 reduce()方法可以執行求數組中所有值之和的操作。
eg:
?
?
reduceRight()的作用類似,只不過方向相反而已。
eg:
?
?
使用 reduce()還是 reduceRight(),主要取決于要從哪頭開始遍歷數組。除此之外,它們完全 相同。
支持這兩個歸并函數的瀏覽器有 IE9+、Firefox 3+、Safari 4+、Opera 10.5 和 Chrome。
?
5.3 Date類型
?
Date 類型使用自 UTC(Coordinated Universal Time,國際協調時間)1970 年 1 月 1 日午夜(零時)開始經過 的毫秒數來保存日期。在使用這種數據存儲格式的條件下,Date 類型保存的日期能夠精確到 1970 年 1 月 1 日之前或之后的 285 616 年。
要創建一個日期對象。
eg:
var now = new Date();
在調用 Date 構造函數而不傳遞參數的情況下,新創建的對象自動獲得當前日期和時間。如果想根 據特定的日期和時間創建日期對象,必須傳入表示該日期的毫秒數(即從 UTC 時間 1970 年 1 月 1 日午 夜起至該日期止經過的毫秒數)。為了簡化這一計算過程,ECMAScript 提供了兩個方法:Date.parse() 和 Date.UTC()。
(1)Date.parse()
其中,Date.parse()方法接收一個表示日期的字符串參數,然后嘗試根據這個字符串返回相應日 期的毫秒數。ECMA-262 沒有定義 Date.parse()應該支持哪種日期格式,因此這個方法的行為因實現 而異,而且通常是因地區而異。將地區設置為美國的瀏覽器通常都接受下列日期格式:
  • “月/日/年”,如 6/13/2004;
  • “英文月名 日,年”,如 January 12,2004;
  • “英文星期幾 英文月名 日 年 時:分:秒 時區”,如 Tue May 25 2004 00:00:00 GMT-0700。
  • ISO 8601 擴展格式 YYYY-MM-DDTHH:mm:ss.sssZ(例如 2004-05-25T00:00:00)。只有兼容
ECMAScript 5 的實現支持這種格式。
例如,要為 2004 年 5 月 25 日創建一個日期對象,可以使用下面的代碼:
var someDate = new Date(Date.parse("May 25, 2004"));
如果傳入 Date.parse()方法的字符串不能表示日期,那么它會返回 NaN。
實際上,如果直接將表 示日期的字符串傳遞給 Date 構造函數,也會在后臺調用 Date.parse()。
var someDate = new Date("May 25, 2004"); 
這行代碼將會得到與前面相同的日期對象。
?
(2)Date.UTC()
Date.UTC()方法同樣也返回表示日期的毫秒數,但它與 Date.parse()在構建值時使用不同的信 息。Date.UTC()的參數分別是年份、基于 0 的月份(一月是 0,二月是 1,以此類推)、月中的哪一天 (1 到 31)、小時數(0 到 23)、分鐘、秒以及毫秒數。在這些參數中,只有前兩個參數(年和月)是必 需的。如果沒有提供月中的天數,則假設天數為 1;如果省略其他參數,則統統假設為 0。
eg:
?
// GMT時間2000年1月1日午夜零時
var y2k = new Date(Date.UTC(2000, 0));
console.log(y2k); // Date {Sat Jan 01 2000 08:00:00 GMT+0800 (CST)}
// GMT時間2005年5月5日 下午5:55:55
var allFives = new Date(Date.UTC(2005, 4, 5, 17, 55, 55));
console.log(allFives); //Date {Fri May 06 2005 01:55:55 GMT+0800 (CST)}
如同模仿 Date.parse()一樣,Date 構造函數也會模仿 Date.UTC(),但有一點明顯不同:日期 和時間都基于本地時區而非 GMT 來創建。不過,Date 構造函數接收的參數仍然與 Date.UTC()相同。
因此,如果第一個參數是數值,Date 構造函數就會假設該值是日期中的年份,而第二個參數是月份,
以此類推。據此,可以將前面的例子重寫如下。
eg:
// GMT時間2000年1月1日午夜零時
var y2k = new Date(2000, 0);
console.log(y2k); // Date {Sat Jan 01 2000 08:00:00 GMT+0800 (CST)}
// GMT時間2005年5月5日 下午5:55:55
var allFives = new Date(2005, 4, 5, 17, 55, 55);
console.log(allFives); // Date {Thu May 05 2005 17:55:55 GMT+0800 (CST)}
以上代碼創建了與前面例子中相同的兩個日期對象,只不過這次的日期都是基于系統設置的本地時 區創建的。
?
eg:
var newDate = new Date(); //本地時間
var dateparse = new Date(Date.parse("11/20/2016"))
var dateP = new Date("11/20/2016");
var dateUTC = new Date(Date.UTC(2016,10,20,15,55,55)); //UTC時間,UTC時間+8=本地時間
var dateU = new Date(2016,10,20,15,55,55); //本地時間
console.log(newDate);
console.log(dateparse);
console.log(dateP);
console.log(dateUTC);
console.log(dateU);
(3)Data.now()
ECMAScript 5 添加了 Data.now()方法,返回表示調用這個方法時的日期和時間的毫秒數。這個方 法簡化了使用 Data 對象分析代碼的工作。例如:
//取得開始時間
var start = Date.now();
//調用函數 doSomething();
//取得停止時間
var stop = Date.now(),
result = stop – start;
支持 Data.now()方法的瀏覽器包括 IE9+、Firefox 3+、Safari 3+、Opera 10.5 和 Chrome。在不支
持它的瀏覽器中,使用+操作符把 Data 對象轉換成字符串,也可以達到同樣的目的。
//取得開始時間var start = +new Date(); 
//調用函數 doSomething(); //取得停止時間
var stop = +new Date(),result = stop - start;
5.3.1 繼承的方法
與其他引用類型一樣,Date 類型也重寫了 toLocaleString()、toString()和 valueOf()方法; 但這些方法返回的值與其他類型中的方法不同。
Date 類型的 toLocaleString()方法會按照與瀏覽器 設置的地區相適應的格式返回日期和時間。
toString()方法則通常返回帶有時區信息的日期和 時間,其中時間一般以軍用時間(即小時的范圍是 0 到 23)表示。
事實上, toLocaleString()和 toString()的這一差別僅在調試代碼時比較有用,而在顯示日期和時間時沒有 什么價值。
至于 Date 類型的 valueOf()方法,則根本不返回字符串,而是返回日期的毫秒表示。因此,可以 方便使用比較操作符(小于或大于)來比較日期值。
eg:
var date1 = new Date(2007, 0, 1);
var date2 = new Date(2007, 1, 1);
console.log(date1 < date2); //true
console.log(date1 > date2); //false 
5.3.2 日期格式化方法
Date 類型還有一些專門用于將日期格式化為字符串的方法,這些方法如下。
  • toDateString()——以特定于實現的格式顯示星期幾、月、日和年;
  • toTimeString()——以特定于實現的格式顯示時、分、秒和時區;
  • toLocaleDateString()——以特定于地區的格式顯示星期幾、月、日和年;
  • toLocaleTimeString()——以特定于實現的格式顯示時、分、秒;
  • toUTCString()——以特定于實現的格式完整的 UTC 日期。
與 toLocaleString()和 toString()方法一樣,以上這些字符串格式方法的輸出也是因瀏覽器 而異的,因此沒有哪一個方法能夠用來在用戶界面中顯示一致的日期信息。
5.3.3 日期/時間組件方法
UTC 日期指的是在沒有時區偏差的情況下(將日期轉換為 GMT 時間) 的日期值。
?
?
5.4 RegExp類型
ECMAScript 通過 RegExp 類型來支持正則表達式。使用下面類似 Perl 的語法,就可以創建一個正則表達式。
var expression = / pattern / flags ;
其中的模式(pattern)部分可以是任何簡單或復雜的正則表達式,可以包含字符類、限定符、分組、向前查找以及反向引用。每個正則表達式都可帶有一或多個標志(flags),用以標明正則表達式的行為。正則表達式的匹配模式支持下列 3 個標志。
  • ?g:表示全局(global)模式,即模式將被應用于所有字符串,而非在發現第一個匹配項時立即 停止;
  • ?i:表示不區分大小寫(case-insensitive)模式,即在確定匹配項時忽略模式與字符串的大小寫;
  • ?m:表示多行(multiline)模式,即在到達一行文本末尾時還會繼續查找下一行中是否存在與模式匹配的項。
因此,一個正則表達式就是一個模式與上述 3 個標志的組合體。不同組合產生不同結果。
eg:
/* 匹配字符串中所有"at"的實例 */var pattern1 = /at/g;
/* 匹配第一個"bat"或"cat",不區分大小寫 */var pattern2 = /[bc]at/i;
/* 匹配所有以"at"結尾的 3 個字符的組合,不區分大小寫*/var pattern3 = /.at/gi;
與其他語言中的正則表達式類似,模式中使用的所有元字符都必須轉義。正則表達式中的元字符包括:
( [ { \ ^ $ | ) ? * + .]}
這些元字符在正則表達式中都有一或多種特殊用途,因此如果想要匹配字符串中包含的這些字符,就必須對它們進行轉義。
eg:
/* 匹配第一個"bat"或"cat",不區分大小寫 */var pattern1 = /[bc]at/i;
/* 匹配第一個" [bc]at",不區分大小寫 */var pattern2 = /\[bc\]at/i;
/* 匹配所有以"at"結尾的 3 個字符的組合,不區分大小寫 */var pattern3 = /.at/gi;
/* 匹配所有".at",不區分大小寫 */var pattern4 = /\.at/gi;
這些例子都是以字面量形式來定義的正則表達式。另一種創建正則表達式的方式是使用 RegExp 構造函數,它接收兩個參數:一個是要匹配的字符串模式,另一個是可選的標志字符串。可以 使用字面量定義的任何表達式,都可以使用構造函數來定義。
eg:
/* 匹配第一個"bat"或"cat",不區分大小寫 */var pattern1 = /[bc]at/i;
/* 與 pattern1 相同,只不過是使用構造函數創建的 */var pattern2 = new RegExp("[bc]at", "i");
在此,pattern1 和 pattern2 是兩個完全等價的正則表達式。要注意的是,傳遞給 RegExp 構造 函數的兩個參數都是字符串(不能把正則表達式字面量傳遞給 RegExp 構造函數)。由于 RegExp 構造 函數的模式參數是字符串,所以在某些情況下要對字符進行雙重轉義。所有元字符都必須雙重轉義,那 些已經轉義過的字符也是如此,例如\n(字符\在字符串中通常被轉義為\\,而在正則表達式字符串中就 會變成\\\\)。
使用正則表達式字面量和使用 RegExp 構造函數創建的正則表達式不一樣。在 ECMAScript 3 中, 正則表達式字面量始終會共享同一個RegExp實例,而使用構造函數創建的每一個新RegExp實例都是一個新實例。
ECMAScript 5 明確規定,使用正則表達式字面量必須像直接調用 RegExp 構造函數一樣,每次都創 建新的 RegExp 實例。IE9+、Firefox 4+和 Chrome 都據此做出了修改。
?
5.4.1 RegExp實例屬性
RegExp 的每個實例都具有下列屬性,通過這些屬性可以取得有關模式的各種信息。
  • global:布爾值,表示是否設置了 g 標志。
  • ignoreCase:布爾值,表示是否設置了 i 標志。
  • lastIndex:整數,表示開始搜索下一個匹配項的字符位置,從 0 算起。
  • multiline:布爾值,表示是否設置了 m 標志。
  • source:正則表達式的字符串表示,按照字面量形式而非傳入構造函數中的字符串模式返回。
source 屬性保存的是規范形式的字符串,即字面量形式所用的字符串。
?
5.4.2 RegExp實例方法
(1)exec()
RegExp 對象的主要方法是 exec(),該方法是專門為捕獲組而設計的。exec()接受一個參數,即 要應用模式的字符串,然后返回包含第一個匹配項信息的數組;或者在沒有匹配項的情況下返回 null。 返回的數組雖然是 Array 的實例,但包含兩個額外的屬性:index 和 input。其中,index 表示匹配 項在字符串中的位置,而 input 表示應用正則表達式的字符串。在數組中,第一項是與整個模式匹配 的字符串,其他項是與模式中的捕獲組匹配的字符串(如果模式中沒有捕獲組,則該數組只包含一項)。
eg:
var text = "mom and dad and baby";
var pattern = /mom( and dad( and baby)?)?/gi;
var matches = pattern.exec(text);
console.log(matches.index);//0
console.log(matches.input);// "mom and dad and baby" 
console.log(matches[0]);// "mom and dad and baby"
console.log(matches[1]);// " and dad and baby"
console.log(matches[2]);// " and baby"
對于 exec()方法而言,即使在模式中設置了全局標志(g),它每次也只會返回一個匹配項。在不 設置全局標志的情況下,在同一個字符串上多次調用 exec()將始終返回第一個匹配項的信息。而在設 置全局標志的情況下,每次調用 exec()則都會在字符串中繼續查找新匹配項。
eg:
var text = "cat, bat, sat, fat";
var pattern1 = /.at/;
var matches = pattern1.exec(text);console.log(matches.index); //0
console.log(matches[0]); //cat
console.log(pattern1.lastIndex); //0
 
matches = pattern1.exec(text);console.log(matches.index); //0 
console.log(matches[0]); //cat 
console.log(pattern1.lastIndex); //0var pattern2 = /.at/g;
var matches = pattern2.exec(text);console.log(matches.index); //0 
console.log(matches[0]); //cat 
console.log(pattern2.lastIndex); //3
IE 的 JavaScript 實現在 lastIndex 屬性上存在偏差,即使在非全局模式下, lastIndex 屬性每次也會變化。
?
(2)test()
test(),它接受一個字符串參數。在模式與該參數匹配的情況下返回 true;否則,返回 false。在只想知道目標字符串與某個模式是否匹配,但不需要知道其文本內容的 情況下,使用這個方法非常方便。因此,test()方法經常被用在 if 語句中
eg:
?
這種用法經常出現在驗證用戶輸入的情況下,因為我們只想知道輸入是不是有效。
(3)
RegExp 實例繼承的 toLocaleString()和 toString()方法都會返回正則表達式的字面量,與創 建正則表達式的方式無關。
eg:
var pattern = new RegExp("\\[bc\\]at", "gi"); 
alert(pattern.toString()); // /\[bc\]at/gi 
alert(pattern.toLocaleString()); // /\[bc\]at/gi
即使上例中的模式是通過調用 RegExp 構造函數創建的,但 toLocaleString()和 toString() 方法仍然會像它是以字面量形式創建的一樣顯示其字符串表示。
正則表達式的 valueOf()方法返回正則表達式本身。
?
5.4.3 RegExp構造函數屬性
RegExp 構造函數包含一些屬性(這些屬性在其他語言中被看成是靜態屬性)。這些屬性適用于作用域中的所有正則表達式,并且基于所執行的最近一次正則表達式操作而變化。關于這些屬性的另一個獨特之處,就是可以通過兩種方式訪問它們。換句話說,這些屬性分別有一個長屬性名和一個短屬性名 (Opera 是例外,它不支持短屬性名)。下表列出了 RegExp 構造函數的屬性。
RegExp 構造函數的各個屬性返回了下列值:
  • ?input 屬性返回了原始字符串;
  • ?leftContext 屬性返回了單詞 short 之前的字符串,而 rightContext 屬性則返回了 short
之后的字符串;
  • ?lastMatch 屬性返回最近一次與整個正則表達式匹配的字符串,即 short;
  • ?lastParen 屬性返回最近一次匹配的捕獲組,即例子中的 s。
eg1:
var text = "this has been a short summer";
var pattern = /(.)hort/g;
/* 注意:Opera 不支持 input、lastMatch、lastParen 和 multiline 屬性 ; Internet Explorer 不支持 multiline 屬性*/if (pattern.test(text)){console.log(RegExp.input); //this has been a short summerconsole.log(RegExp.leftContext); //this has been a console.log(RegExp.rightContext); // summerconsole.log(RegExp.lastMatch); //shortconsole.log(RegExp.lastParen); //sconsole.log(RegExp.multiline); //false
}
eg2:
var text = "this has been a short summer";
var pattern = /(.)hort/g;
/* 注意:Opera 不支持 input、lastMatch、lastParen 和 multiline 屬性 ; Internet Explorer 不支持 multiline 屬性*/if (pattern.test(text)){console.log(RegExp.$_); //this has been a short summerconsole.log(RegExp["$`"]); //this has been a console.log(RegExp["$'"]); // summerconsole.log(RegExp["$&"]); //shortconsole.log(RegExp["$+"]); //sconsole.log(RegExp["$*"]); //false
}
除了上面介紹的幾個屬性之外,還有多達 9 個用于存儲捕獲組的構造函數屬性。訪問這些屬性的語 法是 RegExp.$1、RegExp.$2...RegExp.$9,分別用于存儲第一、第二......第九個匹配的捕獲組。在 調用 exec()或 test()方法時,這些屬性會被自動填充。
eg:
var text = "this has been a short summer"; 
var pattern = /(..)or(.)/g; 
if (pattern.test(text)){alert(RegExp.$1); //sh alert(RegExp.$2); //t 
}
5.4.4 模式的局限性
盡管 ECMAScript 中的正則表達式功能還是比較完備的,但仍然缺少某些語言(特別是 Perl)所支 持的高級正則表達式特性。下面列出了 ECMAScript 正則表達式不支持的特性(要了解更多相關信息, 請訪問 www.regular-expressions.info)。
  • 匹配字符串開始和結尾的\A 和\Z 錨;但支持以插入符號(^)和美元符號($)來匹配字符串的開始和結尾。
  • 向后查找(lookbehind);但完全支持向前查找(lookahead)。
  • 并集和交集類
  • 原子組(atomic grouping)
  • Unicode 支持(單個字符除外,如\uFFFF)
  • 命名的捕獲組;但支持編號的捕獲組。
  • s(single,單行)和 x(free-spacing,無間隔)匹配模式
  • 條件匹配
  • 正則表達式注釋
?
5.5 Function類型
函數實際 上是對象。每個函數都是 Function 類型的實例,而且都與其他引用類型一樣具有屬性和方法。由于函 數是對象,因此函數名實際上也是一個指向函數對象的指針,不會與某個函數綁定。
1.函 數聲明語法定義
function sum (num1, num2) { return num1 + num2; 
}
2.函數表達式定義函數
 var sum = function(num1, num2){ return num1 + num2; 
};
通過變量 sum 即可以引 用函數。另外,還要注意函數末尾有一個分號,就像聲明其他變量時一樣。
3.Function 構造函數
var sum = new Function("num1", "num2", "return num1 + num2"); // 不推薦
Function 構造函數可以接收任意數量的參數, 但最后一個參數始終都被看成是函數體,而前面的參數則枚舉出了新函數的參數。
從技術角度講,這是一個函數表達式。但是,我們不推薦讀者使用這種方法定義函數,因為這種語 法會導致解析兩次代碼(第一次是解析常規 ECMAScript 代碼,第二次是解析傳入構造函數中的字符串), 從而影響性能。
5.5.1 沒有重載(深入理解)
聲明了兩個同名函數,而結果則是后面的函數覆蓋了前面的函數。
eg:
var sum = function(a,b){
return a+b;
};var othersum = sum;var sum = function(c,d){
return c+2*d;
};console.log(sum(10,10)); //30
console.log(othersum(10,10));//20
5.5.2 函數聲明與函數表達式
解析器會率先讀取函數聲明,并使其在執行任何代碼之前可用(可以訪問);至于函數表達式,則必須等到解析器執行到它所在的代碼行,才會真 正被解釋執行。
eg1:
console.log(sum(10,10));
function sum(num1, num2){
return num1 + num2;
}
//20
分析:因為在代碼開始執行之前,解析器就已經通過一個名為函數聲明提升 (function declaration hoisting)的過程,讀取并將函數聲明添加到執行環境中。對代碼求值時,JavaScript 引擎在第一遍會聲明函數并將它們放到源代碼樹的頂部。所以,即使聲明函數的代碼在調用它的代碼后 面,JavaScript 引擎也能把函數聲明提升到頂部。
eg2:
console.log(sumn(10,10));
var sumn = function(num1, num2){
return num1 + num2;
};
//Uncaught TypeError: sumn is not a function(…)
分析:在執行到函數所在的語句之前,變量 sum 中不會保存有對函數的引用;而且,由于第一 行代碼就會導致“unexpected identifier”(意外標識符)錯誤,實際上也不會執行到下一行。
?
也可以同時使用函數聲明和函數表達式,例如 var sum = function sum(){}。 不過,這種語法在 Safari 中會導致錯誤。
?
5.5.3 作為值的函數
因為 ECMAScript 中的函數名本身就是變量,所以函數也可以作為值來使用。也就是說,不僅可以 像傳遞參數一樣把一個函數傳遞給另一個函數,而且可以將一個函數作為另一個函數的結果返回。
eg:
function callSomeFunction(someFunction, someArgument){
return someFunction(someArgument);
}
function add10(num){
return num + 10;
}
var result1 = callSomeFunction(add10, 10);
console.log(result1); //20
function getGreeting(name){
return "Hello, " + name;
}
var result2 = callSomeFunction(getGreeting, "Nicholas");
console.log(result2); //"Hello, Nicholas"
這個函數接受兩個參數。第一個參數應該是一個函數,第二個參數應該是要傳遞給該函數的一個值。
要訪問函數的指針而不執行函數的話,必須去掉函數名后 面的那對圓括號。
假設有一個 對象數組,我們想要根據某個對象屬性對數組進行排序。而傳遞給數組 sort()方法的比較函數要接收 兩個參數,即要比較的值。可是,我們需要一種方式來指明按照哪個屬性來排序。要解決這個問題, 可以定義一個函數,它接收一個屬性名,然后根據這個屬性名來創建一個比較函數。
eg:
//從小到大排序
function createComparisonFunction(propertyName) {
return function(object1, object2){
var value1 = object1[propertyName];
var value2 = object2[propertyName];
if (value1 < value2){
return -1;
} else if (value1 > value2){
return 1;
}
};
}
var data = [{name: "Zachary", age: 28}, {name: "Nicholas", age: 29}];data.sort(createComparisonFunction("name"));
console.log(data[0].name); //Nicholas
 
data.sort(createComparisonFunction("age"));
console.log(data[0].name); //Zachary
5.5.4 函數內部屬性
1.arguments
在函數內部,有兩個特殊的對象:arguments 和 this。其中,arguments是一個類數組對象,包含著傳入函數中的所有參數。雖然 arguments 的主要用途是保存函數參數, 但這個對象還有一個名叫 callee 的屬性,該屬性是一個指針,指向擁有這個arguments 對象的函數。
eg:
//經典階乘函數
function factorial(num){
if (num <=1) {
return 1;
} else {
return num * factorial(num-1)
}
}
console.log(factorial(5)); //120
定義階乘函數一般都要用到遞歸算法;這個函數的執行與函數名 factorial 緊緊耦合在了一起。為 了消除這種緊密耦合的現象,可以像下面這樣使用 arguments.callee。
eg:
function factorial(num){
if (num <=1) {
return 1;
} else {
return num * arguments.callee(num-1)
}
};
console.log(factorial(5)); //120
在這個重寫后的 factorial()函數的函數體內,沒有再引用函數名 factorial。這樣,無論引用 函數時使用的是什么名字,都可以保證正常完成遞歸調用。
eg1:
function factorial(num){
if (num <=1) {
return 1;
} else {
return num * arguments.callee(num-1)
}
};var trueFactorial = factorial;factorial = function(){
return 0;
};console.log(trueFactorial(5)); //120
console.log(factorial(5)); //0
分析:
var trueFactorial = factorial,實際上是在另一個位置上保存了一個函數 的指針。
eg2:
function factorial(num){
  if (num <=1) {return 1;} else {return num * factorial(num-1)} };var trueFactorial = factorial;factorial = function(){ return 0; };console.log(trueFactorial(5)); //0 console.log(factorial(5)); //0
2.this
函數內部的另一個特殊對象是 this,其行為與 Java 和 C#中的 this 大致類似。換句話說,this 引用的是函數據以執行的環境對象——或者也可以說是 this 值(當在網頁的全局作用域中調用函數時, this 對象引用的就是 window)。
eg:
window.color = "red";
var o = { color: "blue" };
function sayColor(){
console.log(this.color);
}
sayColor(); // red
o.sayColor = sayColor;
o.sayColor(); // blue
分析:函數 sayColor()是在全局作用域中定義的,它引用了 this 對象。當在全局作用域中調用 sayColor()時,this 引用的是全局對象 window;而當把這個函數賦給對象 o 并調用 o.sayColor() 2 時,this 引用的是對象 o。
函數的名字僅僅是一個包含指針的變量而已。因此,即使是 在不同的環境中執行,全局的 sayColor()函數與 o.sayColor()指向的仍然是同一 個函數。
?
ECMAScript 5 也規范化了另一個函數對象的屬性:caller。除了 Opera 的早期版本不支持,其他 4 瀏覽器都支持這個 ECMAScript 3 并沒有定義的屬性。這個屬性中保存著調用當前函數的函數的引用, 如果是在全局作用域中調用當前函數,它的值為 null。
eg:
function outer(){
inner();
};
function inner(){
alert(inner.caller);
};
outer();
//function outer(){inner();}
分析:因為 outer()調用了 inter(),所以inner.caller 就指向 outer()。為了實現更松散的耦合,也可以通過 arguments.callee.caller來訪問相同的信息。
eg:
function outer(){ inner();} 

function inner(){ alert(arguments.callee.caller); } outer(); // function outer(){inner();}
IE、Firefox、Chrome 和 Safari 的所有版本以及 Opera 9.6 都支持 caller 屬性。
當函數在嚴格模式下運行時,訪問 arguments.callee 會導致錯誤。ECMAScript 5 還定義了 arguments.caller 屬性,但在嚴格模式下訪問它也會導致錯誤,而在非嚴格模式下這個屬性始終是 undefined。定義這個屬性是為了分清 arguments.caller 和函數的 caller 屬性。以上變化都是為 了加強這門語言的安全性,這樣第三方代碼就不能在相同的環境里窺視其他代碼了。
嚴格模式還有一個限制:不能為函數的 caller 屬性賦值,否則會導致錯誤。
?
5.5.5 函數屬性和方法
?
?

轉載于:https://www.cnblogs.com/xmyun/p/6415296.html

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/284557.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/284557.shtml
英文地址,請注明出處:http://en.pswp.cn/news/284557.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Windows Hook

啥是windows的鉤子&#xff1f;鉤子故名思議就是在嵌入到正常執行程序的功能。對于windows來說&#xff0c;每個系統和應用程序之間的交互是使用消息機制來進行。比如點擊應用程序上面的某個按鈕&#xff0c;就是發送了事件給了應用程序。windows鉤子的作用就是在事件發送給應用…

HTTP協議之Expect爬坑

前言今天&#xff0c;在對接一個第三方平臺開放接口時遇到一個很棘手的問題&#xff0c;根據接口文檔組裝好報文&#xff0c;使用HttpClient發起POST請求時一直超時&#xff0c;對方服務器一直不給任何響應。發起請求的代碼如下&#xff1a;using (var httpClient new HttpCli…

【ArcGIS微課1000例】0028:ArcGIS根據屬性快速分割生成多個shp文件

ArcGIS10.5及以上的版本提供了按屬性分割工具,(分析工具->提取->按屬性分割)工具。也可以使用10.2版本的分割工具,效果應該是一樣的。本文演示使用分割工具批量快速提取一個縣范圍內的多個鎮,生成多個鎮矢量shp數據。 擴展閱讀:【ArcGIS遇上Python】ArcGIS Python按…

Win11 恢復 Win10經典右鍵菜單 親測有效

管理員運行命令&#xff1a; reg.exe add "HKCU\Software\Classes\CLSID\{86ca1aa0-34aa-4e8b-a509-50c905bae2a2}\InprocServer32" /f /ve reg.exe add "HKCU\Software\Classes\CLSID\{86ca1aa0-34aa-4e8b-a509-50c905bae2a2}\InprocServer32" /f /ve 重…

把一個字符串里符合表情文字標簽的地方全部替換為相應的圖片的方法

1、表情數據&#xff1a; var emotion [{"name": "Expression_1","text": "[微笑]"},{"name": "Expression_2","text": "[撇嘴]"},{"name": "Expression_3","text&…

【ArcGIS微課1000例】0029:ArcGIS繪制平行線(構造平行公路)

在實際工作中,有時需要繪制平行線,比如道路兩邊的邊界線,可以使用“平行復制”功能快速繪制平行線,本文介紹如何使用“平行復制”功能快速繪制平行線。 1. 加載公路矢量 加載配套實驗數據包中的數據0029.rar中的矢量數據:公路。 2. 生成平行公路 點擊“編輯器”→“開始…

2017年初隨想——幾個小目標

回顧往事很慘&#xff0c;展望未來渺茫 2016年不順的事情一籮筐&#xff0c;母親追求信仰&#xff08;誤入歧途&#xff09;導致父母離婚&#xff0c;父親又遭遇車禍&#xff0c;現在依然癱瘓在床&#xff0c;意識都尚未清醒&#xff0c;母親卻依然杳無音信。而我則剛工作2年半…

Win11 沒有磁盤清理工具,如何清理磁盤舊的windows.old文件

win11 磁盤右鍵沒有了“磁盤清理工具” 如果想清理文件&#xff0c;可以打開設置&#xff08;WinI&#xff09;系統—存儲—清理建議 您也可以打開“存儲感知”&#xff0c;系統會在需要時幫你自動清理文件。

腳本進階,函數調用實例練習

一、練習&#xff1a;腳本&#xff1a;判定192.168.0.200-192.168.0.254之間哪些主機在線&#xff0c;要求&#xff1a;1、使用函數來實現一臺主機的判定過程&#xff1a;2、在主程序中調用此函數判定指定范圍內的所有主機的在線情況&#xff0c;vim ping.sh#!/bin/bash#PING()…

.NET開發云原生應用,你只差給自己加個油

為什么要云原生&#xff08;Cloud Native&#xff09;Cloud表示應用程序位于云中&#xff0c;而不是傳統的數據中心&#xff1b;Native表示應用程序從設計之初即考慮到云的環境&#xff0c;原生為云而設計&#xff0c;在云上以最佳姿勢運行&#xff0c;充分利用和發揮云平臺的彈…

java成員變量的初始化

2019獨角獸企業重金招聘Python工程師標準>>> 類變量(static變量,不需要實例化對象也可以引用) 實例變量(非static變量,需要實例化對象) 局部變量(類的成員函數中的變量) 初始化方式: 構造函數初始化 變量聲明時初始化 代碼塊初始化 java自動初始化(在構造函數執行之…

Win11 的日歷 替代

Win11 的日歷雖然漂亮&#xff0c;卻少了很多小功能&#xff0c;特別是沒有秒鐘和日程的設計&#xff0c;讓用慣了 Win10 的小伙伴大呼不滿。原來曾經用過360帶的日歷&#xff0c;可惜不支持Win11&#xff0c;下面這個日歷是一款功能強大、顏值很高的小工具&#xff0c;能夠提供…

ReactNative--React簡介

React 基礎框架&#xff0c;是一些實現理念&#xff0c;不能用來做網頁的開發和手機應用的開發 React.js 用來做網頁開發 ReactNative 移動應用開發 在學習ReactNative之前&#xff0c;先學習React http://reactnative.cn/ 中文網 http://facebook.github.io/react-nativ…

【ArcGIS微課1000例】0030:ArcGIS利用MXD doctor工具分析并修復mxd地圖文檔

MXD Doctor 是一個獨立的應用程序,位于 ArcGIS Desktop 安裝目錄下的 Tools 文件夾中。該工具可用于分析已損壞的 .mxd 文件。根據分析結果,可將已損壞的 .mxd 文件中所包含的實體復制到新的或現有 .mxd 文件中。 可以從所有程序 > ArcGIS > Desktop 工具中打開 MXD Do…

分析一個 .NET 寫的 某 RFID標簽系統 CPU暴漲

一&#xff1a;背景 1. 講故事前段時間有位朋友說他的程序 CPU 出現了暴漲現象&#xff0c;由于程序是買來的&#xff0c;所以問題就比較棘手了&#xff0c;那既然找到我&#xff0c;就想辦法幫朋友找出來吧&#xff0c;分析下來&#xff0c;問題比較經典&#xff0c;有必要和大…

linux開機引導過程總覽

簡單的說&#xff0c;系統的啟動過程如下&#xff1a; 1.開機自檢&#xff1a; 按下電源按鍵后&#xff0c;計算機硬件會主動讀取BIOS加載硬件信息并進行硬件的自我測試&#xff0c;然后系統會根據BIOS里的啟動順序讀取第一個可啟動的設備&#xff0c;從而移交系統控制權&#…

CentOS關機與重啟命令詳解

2019獨角獸企業重金招聘Python工程師標準>>> Linux centos重啟命令&#xff1a; 1、reboot  2、shutdown -r now 立刻重啟(root用戶使用)  3、shutdown -r 10 過10分鐘自動重啟(root用戶使用)  4、shutdown -r 20:35 在時間為20:35時候重啟(root用戶使用)如果…

JS正則提取字符串

河北科技師范學院歐美學院新聞標題 河南大學邁阿密學院新聞標題 首都經濟貿易大學密云分校新聞標題 北京科技大學(延慶校區)新聞標題 湖北中醫藥大學職業技術學院新聞標題 公安消防部隊高等專科學校新聞標題 從上邊的類似新聞標題中提取完整學校名稱&#xff0c;最終參考代…

【工具】PC端調試手機端 Html 頁面的工具

一、概述 有一個項目需要在手機端顯示一個 web 頁面&#xff0c;而每次把應用 launch 后&#xff0c;從手機端看比較麻煩&#xff0c;因此搜羅了幾種在 PC 端調試手機端頁面的工具。 二、工具 http://fonkie.iteye.com/blog/1846858 http://blog.csdn.net/dojotoolkit/article/…

【ArcGIS微課1000例】0031:ArcGIS中的32個拓撲規則(圖文詳解)

在地理數據庫中,拓撲是定義點要素、線要素以及面要素共享重疊幾何的方式的排列布置。例如,街道中心線與人口普查區塊共享公共幾何,相鄰的土壤面共享公共邊界。學習拓撲就必須掌握ArcGIS中常見的拓撲規則。 文章目錄 一、面的拓撲規則(10種)二、點的拓撲規則(6種)三、線的…