《JavaScript高級程序設計》讀書筆記 ---單體內置對象

Global對象
Global(全局)對象能夠說是ECMAScript 中最特別的一個對象了,由於無論你從什麼角度上看,這個對象都是不存在的。ECMAScript 中的Global 對象在某種意義上是做爲一個終極的「兜底兒對象」來定義的。換句話說,不屬於任何其餘對象的屬性和方法,最終都是它的屬性和方法。事實上,沒有全局變量或全局函數;全部在全局做用域中定義的屬性和函數,都是Global 對象的屬性。本書前面介紹過的那些函數,諸如isNaN()、isFinite()、parseInt()以及parseFloat(),實際上全都是Global 對象的方法。除此以外,Global 對象還包含其餘一些方法。算法


1. URI 編碼方法
Global 對象的encodeURI()和encodeURIComponent()方法能夠對URI(Uniform Resource Identifiers,通用資源標識符)進行編碼,以便發送給瀏覽器。有效的URI 中不能包含某些字符,例如空格。而這兩個URI 編碼方法就能夠對URI 進行編碼,它們用特殊的UTF-8 編碼替換全部無效的字符,從而讓瀏覽器可以接受和理解。
其中,encodeURI()主要用於整個URI(例如,http://www.wrox.com/illegal value.htm),而encode-URIComponent()主要用於對URI 中的某一段(例如前面URI 中的illegal value.htm)進行編碼。它們的主要區別在於,encodeURI()不會對自己屬於URI 的特殊字符進行編碼,例如冒號、正斜槓、問號和井字號;而encodeURIComponent()則會對它發現的任何非標準字符進行編碼。來看下面的例子。數組

var uri = "http://www.wrox.com/illegal value.htm#start";
//"http://www.wrox.com/illegal%20value.htm#start"
alert(encodeURI(uri));
//"http%3A%2F%2Fwww.wrox.com%2Fillegal%20value.htm%23start"
alert(encodeURIComponent(uri));瀏覽器

使用encodeURI()編碼後的結果是除了空格以外的其餘字符都原封不動,只有空格被替換成了%20。而encodeURIComponent()方法則會使用對應的編碼替換全部非字母數字字符。這也正是能夠對整個URI 使用encodeURI(),而只能對附加在現有URI 後面的字符串使用encodeURIComponent() 的緣由所在。安全

注:通常來講, 咱們使用encodeURIComponent() 方法的時候要比使用encodeURI()更多,由於在實踐中更常見的是對查詢字符串參數而不是對基礎URI進行編碼。app

與encodeURI()和encodeURIComponent()方法對應的兩個方法分別是decodeURI()和decodeURIComponent()。其中,decodeURI()只能對使用encodeURI()替換的字符進行解碼。例如,它可將%20 替換成一個空格,但不會對%23 做任何處理,由於%23 表示井字號(#),而井字號不是使用encodeURI()替換的。一樣地,decodeURIComponent()可以解碼使用encodeURIComponent()編碼的全部字符,即它能夠解碼任何特殊字符的編碼。來看下面的例子:dom

var uri = "http%3A%2F%2Fwww.wrox.com%2Fillegal%20value.htm%23start";
//http%3A%2F%2Fwww.wrox.com%2Fillegal value.htm%23start
alert(decodeURI(uri));
//http://www.wrox.com/illegal value.htm#start
alert(decodeURIComponent(uri));函數

這裏,變量uri 包含着一個由encodeURIComponent()編碼的字符串。在第一次調用decodeURI()輸出的結果中,只有%20 被替換成了空格。而在第二次調用decodeURIComponent()輸出的結果中,全部特殊字符的編碼都被替換成了原來的字符,獲得了一個未經轉義的字符串(但這個字符串並非一個有效的URI)。this

 

2. eval()方法
如今,咱們介紹最後一個——大概也是整個ECMAScript 語言中最強大的一個方法:eval()。eval() 方法就像是一個完整的ECMAScript 解析器,它只接受一個參數,即要執行的ECMAScript (或JavaScript)字符串。看下面的例子:
eval("alert('hi')");
這行代碼的做用等價於下面這行代碼:
alert("hi");
當解析器發現代碼中調用eval()方法時,它會將傳入的參數看成實際的ECMAScript 語句來解析,而後把執行結果插入到原位置。經過eval()執行的代碼被認爲是包含該次調用的執行環境的一部分,所以被執行的代碼具備與該執行環境相同的做用域鏈。這意味着經過eval()執行的代碼能夠引用在包含環境中定義的變量,舉個例子:
var msg = "hello world";
eval("alert(msg)");   //"hello world"
可見,變量msg 是在eval()調用的環境以外定義的,但其中調用的alert()仍然可以顯示"hello world"。這是由於上面第二行代碼最終被替換成了一行真正的代碼。一樣地,咱們也能夠在eval()調用中定義一個函數,而後再在該調用的外部代碼中引用這個函數:
eval("function sayHi() { alert('hi'); }");
sayHi();
顯然,函數sayHi()是在eval()內部定義的。但因爲對eval()的調用最終會被替換成定義函數的實際代碼,所以能夠在下一行調用sayHi()。對於變量也同樣:編碼

eval("var msg = 'hello world'; ");
alert(msg); //"hello world"
在eval()中建立的任何變量或函數都不會被提高,由於在解析代碼的時候,它們被包含在一個字符串中;它們只在eval()執行的時候建立。
嚴格模式下,在外部訪問不到eval()中建立的任何變量或函數,所以前面兩個例子都會致使錯誤。一樣,在嚴格模式下,爲eval 賦值也會致使錯誤:
"use strict";
eval = "hi"; //causes errorcode

注:可以解釋代碼字符串的能力很是強大,但也很是危險。所以在使用eval()時必須極爲謹慎,特別是在用它執行用戶輸入數據的狀況下。不然,可能會有惡意用戶輸入威脅你的站點或應用程序安全的代碼(即所謂的代碼注入)。

 

3. Global 對象的屬性
Global 對象還包含一些屬性,其中一部分屬性已經在本書前面介紹過了。例如,特殊的值undefined、NaN 以及Infinity 都是Global 對象的屬性。此外,全部原生引用類型的構造函數,像Object 和Function,也都是Global 對象的屬性。下表列出了Global 對象的全部屬性。

 

 

ECMAScript 5 明確禁止給undefined、NaN 和Infinity 賦值,這樣作即便在非嚴格模式下也會致使錯誤。


4. window 對象
ECMAScript 雖然沒有指出如何直接訪問Global 對象,但Web 瀏覽器都是將這個全局對象做爲window 對象的一部分加以實現的。所以,在全局做用域中聲明的全部變量和函數,就都成爲了window對象的屬性。來看下面的例子。
var color = "red";
function sayColor(){
  alert(window.color);
}
window.sayColor();   //"red"

 這裏定義了一個名爲color 的全局變量和一個名爲sayColor()的全局函數。在sayColor()內部,咱們經過window.color 來訪問color 變量,以說明全局變量是window 對象的屬性。而後,又使用window.sayColor()來直接經過window 對象調用這個函數,結果顯示在了警告框中。

 注:JavaScript中的window 對象除了扮演ECMAScript規定的Global 對象的角色外,還承擔了不少別的任務。第8 章在討論瀏覽器對象模型時將詳細介紹window 對象。

另外一種取得Global 對象的方法是使用如下代碼:
var global = function(){
  return this;
}();
以上代碼建立了一個當即調用的函數表達式,返回this 的值。如前所述,在沒有給函數明確指定this 值的狀況下(不管是經過將函數添加爲對象的方法,仍是經過調用call()或apply()),this值等於Global 對象。而像這樣經過簡單地返回this 來取得Global 對象,在任何執行環境下都是可行的。第7 章將深刻討論函數表達式。

 

Math對象
ECMAScript 還爲保存數學公式和信息提供了一個公共位置,即Math 對象。與咱們在JavaScript 直接編寫的計算功能相比,Math 對象提供的計算功能執行起來要快得多。Math 對象中還提供了輔助完成這些計算的屬性和方法。
1. Math 對象的屬性
Math 對象包含的屬性大都是數學計算中可能會用到的一些特殊值。下表列出了這些屬性。

 

 

雖然討論這些值的含義和用途超出了本書範圍,但你確實能夠隨時使用它們。
2. min()和max()方法
Math 對象還包含許多方法,用於輔助完成簡單和複雜的數學計算。
其中,min()和max()方法用於肯定一組數值中的最小值和最大值。這兩個方法均可以接收任意多個數值參數,以下面的例子所示。

var max = Math.max(3, 54, 32, 16);
alert(max); //54
var min = Math.min(3, 54, 32, 16);
alert(min); //3

 

對於三、5四、32 和16,Math.max()返回54,而Math.min()返回3。這兩個方法常常用於避免多餘的循環和在if 語句中肯定一組數的最大值。
要找到數組中的最大或最小值,能夠像下面這樣使用apply()方法。
var values = [1, 2, 3, 4, 5, 6, 7, 8];
var max = Math.max.apply(Math, values);
這個技巧的關鍵是把Math 對象做爲apply()的第一個參數,從而正確地設置this 值。而後,能夠將任何數組做爲第二個參數。
3. 舍入方法
下面來介紹將小數值舍入爲整數的幾個方法:Math.ceil()、Math.floor()和Math.round()。
這三個方法分別遵循下列舍入規則:
 Math.ceil()執行向上舍入,即它老是將數值向上舍入爲最接近的整數;
 Math.floor()執行向下舍入,即它老是將數值向下舍入爲最接近的整數;
 Math.round()執行標準舍入,即它老是將數值四捨五入爲最接近的整數(這也是咱們在數學課上學到的舍入規則)。
下面是使用這些方法的示例:
alert(Math.ceil(25.9)); //26
alert(Math.ceil(25.5)); //26
alert(Math.ceil(25.1)); //26
alert(Math.round(25.9)); //26
alert(Math.round(25.5)); //26
alert(Math.round(25.1)); //25
alert(Math.floor(25.9)); //25
alert(Math.floor(25.5)); //25
alert(Math.floor(25.1)); //25

對於全部介於25 和26(不包括26)之間的數值,Math.ceil()始終返回26,由於它執行的是向上舍入。Math.round()方法只在數值大於等於25.5 時返回26;不然返回25。最後,Math.floor()對全部介於25 和26(不包括26)之間的數值都返回25。
4. random()方法
Math.random()方法返回大於等於0 小於1 的一個隨機數。對於某些站點來講,這個方法很是實用,由於能夠利用它來隨機顯示一些名人名言和新聞事件。套用下面的公式,就能夠利用Math.random()從某個整數範圍內隨機選擇一個值。
值 = Math.floor(Math.random() * 可能值的總數 + 第一個可能的值)

公式中用到了Math.floor()方法,這是由於Math.random()總返回一個小數值。而用這個小數值乘以一個整數,而後再加上一個整數,最終結果仍然仍是一個小數。舉例來講,若是你想選擇一個1到10 之間的數值,能夠像下面這樣編寫代碼:
var num = Math.floor(Math.random() * 10 + 1);

總共有10 個可能的值(1 到10),而第一個可能的值是1。而若是想要選擇一個介於2 到10 之間的值,就應該將上面的代碼改爲這樣:
var num = Math.floor(Math.random() * 9 + 2);

從2 數到10 要數9 個數,所以可能值的總數就是9,而第一個可能的值就是2。多數狀況下,其實均可以經過一個函數來計算可能值的總數和第一個可能的值,例如:
function selectFrom(lowerValue, upperValue) {
  var choices = upperValue - lowerValue + 1;
  return Math.floor(Math.random() * choices + lowerValue);
}
var num = selectFrom(2, 10);
alert(num); // 介於 2 和10 之間(包括 2 和 10)的一個數值

函數selectFrom()接受兩個參數:應該返回的最小值和最大值。而用最大值減最小值再加1 獲得了可能值的總數,而後它又把這些數值套用到了前面的公式中。這樣,經過調用selectFrom(2,10)就能夠獲得一個介於2 和10 之間(包括2 和10)的數值了。利用這個函數,能夠方便地從數組中隨機取出一項,例如:
var colors = ["red", "green", "blue", "yellow", "black", "purple", "brown"];
var color = colors[selectFrom(0, colors.length-1)];
aler t(color); // 多是數組中包含的任何一個字符串

在這個例子中,傳遞給selectFrom()的第二個參數是數組的長度減1,也就是數組中最後一項的位置。
5. 其餘方法
Math 對象中還包含其餘一些與完成各類簡單或複雜計算有關的方法,但詳細討論其中每個方法的細節及適用情形超出了本書的範圍。下面咱們就給出一個表格,其中列出了這些沒有介紹到的Math對象的方法。 

雖然ECMA-262 規定了這些方法,但不一樣實現可能會對這些方法採用不一樣的算法。畢竟,計算某個值的正弦、餘弦和正切的方式多種多樣。也正由於如此,這些方法在不一樣的實現中可能會有不一樣的精度。

相關文章
相關標籤/搜索