javascript高級程序設計(第三版)學習摘錄上

把近期看高程這本書作的筆記摘錄整理出來了,總歸對原生javascript理論有了一個比較全面的的認識,此次把書中的一些知識要點摘錄出來了,便於之後查閱的時候有方向,也更有效率!!javascript

第一章、javascript簡介

  • 010一、完整的javascript有三部分組成:核心ECMAScript,DOM和BOM
  • 010二、ECMAScript規定了語言的下列組成部分:語法,類型,語句,關鍵字,保留字,操做符,對象

第二章、在html中使用javascript

  • 020一、HTML4.01爲script定義了下列6個屬性:async:可選,表示當即下載腳本,不阻塞;charset:可選,指定字符集;defer:可選,延遲到文檔徹底被解析和顯示以後再執行;language:已廢棄;src:可選,包含要執行代碼的外部文件;type:可選,腳本語言的內容類型
  • 020二、標籤的位置:全部script元素都應該放在頁面的<body>元素頁面內容的後面
  • 020三、IE8之後不支持defer屬性
  • 020四、async屬性的目的是不讓頁面等待腳本下載和執行,從而異步加載頁面其餘內容
  • 020五、<小於號在XHTML中會被看成開始一個新標籤來解析
  • 020六、noscript包含該元素的內容只有在如下狀況纔會顯示出來:不支持腳本,支持腳本但被禁用

第三章、基本概念

  • 030一、標識符,就是指變量、函數、屬性的名字,或者函數的參數:第一個字符必須是一個字母、下劃線( _ )或一個美圓符號( $ );

其餘字符能夠是字母、下劃線、美圓符號或數字html

  • 030二、嚴格模式下,ECMAScript 3 中的一些不肯定的行爲將獲得處理,並且對某些不安全的操做也會拋出錯誤。在函數內部的上方包含這條編譯指示,也能夠指定函數在嚴格模式下執行
  • 030三、加上這個分號能夠避免不少錯誤,加上分號也會在某些狀況下增進代碼的性能,由於這樣解析器就沒必要再花時間推測應該在哪裏插入分號了
  • 030四、用 var 操做符定義的變量將成爲定義該變量的做用域中的局部變量。也就是說,若是在函數中使用 var 定義一個變量,那麼這個變量在函數退出後就會被銷燬。雖然省略 var 操做符能夠定義全局變量,但這也不是咱們推薦的作法。給未經聲明的變量賦值在嚴格模式下會致使拋出 ReferenceError 錯誤
  • 030五、ECMAScript 中有 5 種簡單數據類型(也稱爲基本數據類型):Undefined 、Null、Boolean 、Number和 String 。還有 1種複雜數據類型—— Object , Object 本質上是由一組無序的名值對組成的
  • 030六、Safari 5 及以前版本、Chrome 7 及以前版本在對正則表達式調用 typeof 操做符時會返回 "function" ,而其餘瀏覽器在這種狀況下會返回"object"
  • 030七、對未經聲明的變量調用 delete 不會致使錯誤,但這樣作沒什麼實際意義,並且在嚴格模式下確實會致使錯誤
  • 030八、對未初始化和未聲明的變量執行 typeof 操做符都返回了 undefined 值;這個結果有其邏輯上的合理性。由於雖然這兩種變量從技術角度看有本質區別,但實際上不管對哪一種變量也不可能執行真正的操做
  • 030九、若是定義的變量準備在未來用於保存對象,那麼最好將該變量初始化爲 null 而不是其餘值。只要意在保存對象的變量尚未真正保存對象,就應該明確地讓該變量保存null值。這樣作不只能夠體現 null 做爲空對象指針的慣例,並且也有助於進一步區分null和undefined
  • 03十、要將一個值轉換爲其對應的 Boolean 值,能夠調用轉型函數 Boolean()
  • 03十一、八進制字面值的第一位必須是零(0),而後是八進制數字序列(0~7)。若是字面值中的數值超出了範圍,那麼前導零將被忽略,後面的數值將被看成十進制數值解析
  • 03十二、十六進制字面值的前兩位必須是 0x,後跟任何十六進制數字(0~9 及 A~F)。其中,字母 A~F能夠大寫,也能夠小寫
  • 031三、保存浮點數值須要的內存空間是保存整數值的兩倍,所以 ECMAScript會不失時機地將浮點數值轉換爲整數值
  • 031四、在默認狀況下,ECMASctipt 會將那些小數點後面帶有 6 個零以上的浮點數值轉換爲以 e 表示法表示的數值(例如,0.0000003 會被轉換成 3e-7)
  • 031五、浮點數值的最高精度是 17 位小數,但在進行算術計算時其精確度遠遠不如整數。例如,0.1 加 0.2的結果不是 0.3,而是 0.30000000000000004。這個小小的舍入偏差會致使沒法測試特定的浮點數值
  • 031六、要想肯定一個數值是否是有窮的(換句話說,是否是位於最小和最大的數值之間),可使用 isFinite() 函數。這個函數在參數位於最小與最大數值之間時會返回 true
  • 031七、NaN 與任何值都不相等,包括 NaN自己1八、 isNaN() 在接收到一個值以後,會嘗試將這個值轉換爲數值。某些不是數值的值會直接轉換爲數值,例如字符串 "10" 或 Boolean 值。而任何不能被轉換爲數值的值都會致使這個函數返回true
  • 031八、儘管有點兒難以想象,但 isNaN() 確實也適用於對象。在基於對象調用 isNaN()函數時,會首先調用對象的 valueOf() 方法,而後肯定該方法返回的值是否能夠轉換爲數值。若是不能,則基於這個返回值再調用 toString() 方法,再測試返回值。而這個過程也是 ECMAScript中內置函數和操做符的通常執行流程
  • 031九、因爲 Number() 函數在轉換字符串時比較複雜並且不夠合理,所以在處理整數的時候更經常使用的是parseInt()函數。parseInt() 函數在轉換字符串時,更多的是看其是否符合數值模式。它會忽略字符串前面的空格,直至找到第一個非空格字符。若是第一個字符不是數字字符或者負號, parseInt()就會返回 NaN ;也就是說,用 parseInt() 轉換空字符串會返回 NaN ( Number() 對空字符返回 0)。若是第一個字符是數字字符, parseInt() 會繼續解析第二個字符,直到解析完全部後續字符或者遇到了一個非數字字符。例如, "1234blue" 會被轉換爲 1234,由於 "blue" 會被徹底忽略。相似地, "22.5"會被轉換爲 22,由於小數點並非有效的數字字符。
  • 0320、除了第一個小數點有效以外, parseFloat() 與 parseInt() 的第二個區別在於它始終都會忽略前導的零, parseFloat() 只解析十進制值
  • 032一、ECMAScript 中的字符串是不可變的,也就是說,字符串一旦建立,它們的值就不能改變。要改變某個變量保存的字符串,首先要銷燬原來的字符串,而後再用另外一個包含新值的字符串填充該變量
  • 032二、Object 的每一個實例都具備下列屬性和方法:constructor :保存着用於建立當前對象的函數。對於前面的例子而言,構造函數(constructor)就是 Object(); hasOwnProperty(propertyName) :用於檢查給定的屬性在當前對象實例中(而不是在實例的原型中)是否存在。其中,做爲參數的屬性名( propertyName )必須以字符串形式指定(例如: o.hasOwnProperty("name") );isPrototypeOf(object) :用於檢查傳入的對象是不是傳入對象的原型;propertyIsEnumerable(propertyName) :用於檢查給定的屬性是否可以使用 for-in 語句(本章後面將會討論)來枚舉。與 hasOwnProperty() 方法同樣,做爲參數的屬性名必須以字符串形式指定;toLocaleString() :返回對象的字符串表示,該字符串與執行環境的地區對應;toString() :返回對象的字符串表示;valueOf() :返回對象的字符串、數值或布爾值表示。一般與 toString() 方法的返回值相同
  • 032三、在應用於對象時,相應的操做符一般都會調用對象的 valueOf()和(或) toString() 方法,以便取得能夠操做的值
  • 032四、使用 while 循環作不到的,使用 for 循環一樣也作不到。也就是說, for 循環只是把與循環有關的代碼集中在了一個位置
  • 032五、Safari 3 之前版本的 for-in 語句中存在一個 bug,該 bug 會致使某些屬性被返回兩次。
  • 032六、break 和 continue 語句用於在循環中精確地控制代碼的執行。其中, break 語句會當即退出循環,強制繼續執行循環後面的語句。而 continue 語句雖然也是當即退出循環,但退出循環後會從循環的頂部繼續執行
  • 032七、with 語句的做用是將代碼的做用域設置到一個特定的對象中。嚴格模式下不容許使用 with 語句,不然將視爲語法錯誤。因爲大量使用 with 語句會致使性能降低,同時也會給調試代碼形成困難,所以在開發大型應用程序時,不建議使用 with 語句
with(location){
    var qs = search.substring(1);
    var hostName = hostname;
    var url = href;
}
  • 032八、經過爲每一個 case 後面都添加一個 break 語句,就能夠避免同時執行多個 case代碼的狀況。假如確實須要混合幾種情形,不要忘了在代碼中添加註釋,說明你是有意省略了 break 關鍵字。雖然 ECMAScript 中的 switch 語句借鑑自其餘語言,但這個語句也有本身的特點。首先,能夠在switch 語句中使用任何數據類型(在不少其餘語言中只能使用數值),不管是字符串,仍是對象都沒有問題。其次,每一個 case 的值不必定是常量,能夠是變量,甚至是表達式
switch (i) {
    case 25:
    /*  合併兩種情形 */
    case 35:
        alert("25 or 35");
        break;
    case 45:
        alert("45");
    break;
    default:
        alert("Other");
}
  • 032九、switch 語句在比較值時使用的是全等操做符,所以不會發生類型轉換(例如,字符串 "10" 不等於數值 10)
  • 0330、函數會在執行完 return 語句以後中止並當即退出。所以,位於 return 語句以後的任何代碼都永遠不會執行
  • 033一、 return 語句也能夠不帶有任何返回值。在這種狀況下,函數在中止執行後將返回 undefined值。這種用法通常用在須要提早中止函數執行而又不須要返回值的狀況下
  • 033二、嚴格模式對函數有一些限制:不能把函數命名爲 eval 或 arguments ;不能把參數命名爲 eval 或 arguments ; 不能出現兩個命名參數同名的狀況。若是發生以上狀況,就會致使語法錯誤,代碼沒法執行
  • 033三、函數體內能夠經過 arguments 對象來訪問這個參數數組,從而獲取傳遞給函數的每個參數。 arguments 對象只是與數組相似(它並非 Array 的實例),由於可使用方括號語法訪問它的每個元素(即第一個元素是 arguments[0] ,第二個元素是 argumetns[1] ,以此類推),使用 length 屬性來肯定傳遞進來多少個參數
  • 033四、沒有傳遞值的命名參數將自動被賦予 undefined 值
  • 033五、嚴格模式對如何使用 arguments 對象作出了一些限制。把 arguments[1] 設置爲 10 , num2 的值仍然仍是 undefined 。其次,重寫arguments 的值會致使語法錯誤(代碼將不會執行)
  • 033六、ECMAScript 中的全部參數傳遞的都是值,不可能經過引用傳遞參數
  • 033七、經過檢查傳入函數中參數的類型和數量並做出不一樣的反應,能夠模仿方法的重載
  • 033八、 ECMAScript 中的基本數據類型包括 Undefined 、 Null 、 Boolean 、 Number 和 String
  • 033九、與其餘語言不一樣,ECMScript 沒有爲整數和浮點數值分別定義不一樣的數據類型, Number 類型可用於表示全部數值
  • 0340、ECMAScript 中也有一種複雜的數據類型,即 Object 類型,該類型是這門語言中全部對象的基礎類型
  • 034一、未指定返回值的函數返回的是一個特殊的 undefined 值
  • 034二、 能夠向 ECMAScript 函數傳遞任意數量的參數,而且能夠經過 arguments 對象來訪問這些參數
  • 034三、當複製保存着對象的某個變量時,操做的是對象的引用。但在爲對象添加屬性時,操做的是實際的對象

第四章、變量、做用域和內存問題

  • 040一、 typeof 操做符是肯定一個變量是字符串、數值、布爾值,仍是 undefined 的最佳工具
  • 040二、一般,咱們並非想知道某個值是對象,而是想知道它是什麼類型的對象。爲此,ECMAScript提供了 instanceof 操做符
  • 040三、函數參數也被看成變量來對待,所以其訪問規則與執行環境中的其餘變量相同
  • 040四、在catch 語句中捕獲的錯誤對象會被添加到執行環境的變量對象,而不是 catch 語句的變量對象中。換句話說,即便是在 catch 塊的外部也能夠訪問到錯誤對象
  • 040五、變量查詢也不是沒有代價的。很明顯,訪問局部變量要比訪問全局變量更快,由於不用向上搜索做用域鏈。JavaScript 引擎在優化標識符查詢方面作得不錯,所以這個差異在未來恐怕就能夠忽略不計了
  • 040六、一旦數據再也不有用,最好經過將其值設置爲 null 來釋放其引用——這個作法叫作解除引用(dereferencing)
  • 040七、基本類型值在內存中佔據固定大小的空間,所以被保存在棧內存中
  • 040八、 從一個變量向另外一個變量複製基本類型的值,會建立這個值的一個副本
  • 040九、引用類型的值是對象,保存在堆內存中
  • 04十、包含引用類型值的變量實際上包含的並非對象自己,而是一個指向該對象的指針
  • 04十一、從一個變量向另外一個變量複製引用類型的值,複製的實際上是指針,所以兩個變量最終都指向同一個對象
  • 04十二、肯定一個值是哪一種基本類型可使用 typeof 操做符,而肯定一個值是哪一種引用類型可使用instanceof 操做符
  • 041三、 「標記清除」是目前主流的垃圾收集算法,這種算法的思想是給當前不使用的值加上標記,而後再回收其內存
  • 041四、解除變量的引用不只有助於消除循環引用現象,並且對垃圾收集也有好處。爲了確保有效地回收內存,應該及時解除再也不使用的全局對象、全局對象屬性以及循環引用變量的引用
  • 041五、除非必須使用變量來訪問屬性,不然咱們建議使用點表示法

第五章、引用類型

  • 050一、與對象同樣,在使用數組字面量表示法時,也不會調用 Array 構造函數(Firefox 3及更早版本除外)
  • 050二、數組最多能夠包含 4 294 967 295 個項,這幾乎已經可以知足任何編程需求了。若是想添加的項數超過這個上限值,就會發生異常。而建立一個初始大小與這個上限值接近的數組,則可能會致使運行時間超長的腳本錯誤
  • 050三、全部對象都具備 toLocaleString() 、 toString() 和 valueOf() 方法。其中,調用數組的 toString() 方法會返回由數組中每一個值的字符串形式拼接而成的一個以逗號分隔的字符串。而調用 valueOf() 返回的仍是數組。實際上,爲了建立這個字符串會調用數組每一項的 toString() 方法
  • 050四、 toLocaleString() 方法常常也會返回與 toString() 和 valueOf() 方法相同的值,但也不老是如此
  • 050五、若是數組中的某一項的值是 null 或者 undefined ,那麼該值在 join() 、toLocaleString() 、 toString() 和 valueOf() 方法返回的結果中以空字符串表示
  • 050六、push() 方法能夠接收任意數量的參數,把它們逐個添加到數組末尾,並返回修改後數組的長度。而pop() 方法則從數組末尾移除最後一項,減小數組的 length 值,而後返回移除的項
  • 050七、棧數據結構的訪問規則是 LIFO(後進先出),而隊列數據結構的訪問規則是 FIFO(First-In-First-Out,先進先出)
  • 050八、結合使用 shift() 和 push() 方法,能夠像使用隊列同樣使用數組
  • 050九、同時使用 unshift() 和 pop() 方法,能夠從相反的方向來模擬隊列,即在數組的前端添加項,從數組末端移除項
  • 05十、alert([0, 1, 5, 10, 15].sort());//0,1,10,15,5。可見,即便例子中值的順序沒有問題,但 sort() 方法也會根據測試字符串的結果改變原來的順序。由於數值 5 雖然小於 10,但在進行字符串比較時, "10" 則位於 "5" 的前面,因而數組的順序就被修改了。不用說,這種排序方式在不少狀況下都不是最佳方案。比較函數接收兩個參數,若是第一個參數應該位於第二個以前則返回一個負數,若是兩個參數相等則返回 0,若是第一個參數應該位於第二個以後則返回一個正數
  • 05十一、因爲比較函數經過返回一個小於零、等於零或大於零的值來影響排序結果,所以減法操做就能夠適當地處理全部這些狀況
  • 05十二、 concat() 方法會先建立當前數組一個副本,而後將接收到的參數添加到這個副本的末尾,最後返回新構建的數組。在沒有給 concat() 方法傳遞參數的狀況下,它只是複製當前數組並返回副本。若是傳遞給 concat() 方法的是一或多個數組,則該方法會將這些數組中的每一項都添加到結果數組中。若是傳遞的值不是數組,這些值就會被簡單地添加到結果數組的末尾
  • 051三、slice() 方法能夠接受一或兩個參數,即要返回項的起始和結束位置。在只有一個參數的狀況下, slice() 方法返回從該參數指定位置開始到當前數組末尾的全部項。若是有兩個參數,該方法返回起始和結束位置之間的項——但不包括結束位置的項。注意, slice() 方法不會影響原始數組
  • 051四、若是 slice() 方法的參數中有一個負數,則用數組長度加上該數來肯定相應的位置。例如,在一個包含5項的數組上調用 slice(-2,-1) 與調用 slice(3,4) 獲得的結果相同。若是結束位置小於起始位置,則返回空數組
  • 051五、splice() 方法能夠刪除任意數量的項,只需指定2個參數:要刪除的第一項的位置和要刪除的項數;能夠向指定位置插入任意數量的項,只需提供 3 個參數:起始位置、0(要刪除的項數)和要插入的項。若是要插入多個項,能夠再傳入第4、第五,以致任意多個項;能夠向指定位置插入任意數量的項,且同時刪除任意數量的項,只需指定3個參數:起始位置、要刪除的項數和要插入的任意數量的項。插入的項數沒必要與刪除的項數相等
  • 051六、splice() 方法始終都會返回一個數組,該數組中包含從原始數組中刪除的項(若是沒有刪除任何項,則返回一個空數組)
  • 051七、 indexOf() 和 lastIndexOf()。這兩個方法都接收兩個參數:要查找的項和(可選的)表示查找起點位置的索引。其中, indexOf() 方法從數組的開頭(位置0)開始向後查找,lastIndexOf()方法則從數組的末尾開始向前查找。這兩個方法都返回要查找的項在數組中的位置,或者在沒找到的狀況下返回-1。支持它們的瀏覽器包括 IE9+、Firefox 2+、Safari3+、Opera 9.5+和 Chrome
  • 051八、ECMAScript 5 爲數組定義了5個迭代方法,這些方法中的函數會接收三個參數:數組項的值、該項在數組中的位置和數組對象自己。every() :對數組中的每一項運行給定函數,若是該函數對每一項都返回true,則返回true;filter():對數組中的每一項運行給定函數,返回該函數會返回true的項組成的數組;forEach():對數組中的每一項運行給定函數。這個方法沒有返回值;map() :對數組中的每一項運行給定函數,返回每次函數調用的結果組成的數組;some():對數組中的每一項運行給定函數,若是該函數對任一項返回 true ,則返回 true。以上方法都不會修改數組中的包含的值
  • 051九、這些數組方法經過執行不一樣的操做,能夠大大方便處理數組的任務。支持這些迭代方法的瀏覽器有IE9+、Firefox2+、Safari 3+、Opera 9.5+和 Chrome
  • 0520、 reduce() 和 reduceRight()。這兩個方法都會迭代數組的全部項,而後構建一個最終返回的值。這兩個方法都接收兩個參數:一個在每一項上調用的函數和(可選的)做爲歸併基礎的初始值。傳給reduce()和reduceRight()的函數接收4個參數:前一個值、當前值、項的索引和數組對象。這個函數返回的任何值都會做爲第一個參數自動傳給下一項。第一次迭代發生在數組的第二項上,所以第一個參數是數組的第一項,第二個參數就是數組的第二項。使用reduce()方法能夠執行求數組中全部值之和的操做
  • 052一、使用 reduce() 仍是 reduceRight() ,主要取決於要從哪頭開始遍歷數組。除此以外,它們徹底相同
  • 052二、在調用 Date 構造函數而不傳遞參數的狀況下,新建立的對象自動得到當前日期和時間
  • 052三、 Date.parse() 方法接收一個表示日期的字符串參數,而後嘗試根據這個字符串返回相應日期的毫秒數。ECMA-262沒有定義Date.parse() 應該支持哪一種日期格式,所以這個方法的行爲因實現而異,並且一般是因地區而異
  • 052四、若是傳入 Date.parse()方法的字符串不能表示日期,那麼它會返回NaN。實際上,若是直接將表示日期的字符串傳遞給 Date 構造函數,也會在後臺調用 Date.parse() 。換句話說,下面的代碼與前面的例子是等價的:var someDate = new Date("May 25, 2004");
  • 052五、Date.UTC() 方法一樣也返回表示日期的毫秒數,但它與Date.parse()在構建值時使用不一樣的信息。Date.UTC()的參數分別是年份、基於 0 的月份(一月是0,二月是1,以此類推)、月中的哪一天(1到31)、小時數(0到23)、分鐘、秒以及毫秒數。在這些參數中,只有前兩個參數(年和月)是必需的。若是沒有提供月中的天數,則假設天數爲1;若是省略其餘參數,則通通假設爲 0。
  • 052六、ECMAScript 5 添加了 Data.now() 方法,返回表示調用這個方法時的日期和時間的毫秒數
  • 052七、支持 Data.now() 方法的瀏覽器包括IE9+、Firefox3+、Safari3+、Opera10.5和Chrome。在不支持它的瀏覽器中,使用+操做符把 Data 對象轉換成字符串,也能夠達到一樣的目的
  • 052八、正則表達式。字面量聲明和構造函數聲明的區別,字面量始終會共享一個RegExp實例,而使用構造函數建立的每個新RegExp實例都是一個新實例
  • 052九、RegExp 對象的主要方法是 exec() ,該方法是專門爲捕獲組而設計的。 exec() 接受一個參數,即要應用模式的字符串,而後返回包含第一個匹配項信息的數組;或者在沒有匹配項的狀況下返回 null 。返回的數組雖然是 Array 的實例,但包含兩個額外的屬性: index 和 input 。其中, index 表示匹配項在字符串中的位置,而 input 表示應用正則表達式的字符串。在數組中,第一項是與整個模式匹配的字符串,其餘項是與模式中的捕獲組匹配的字符串(若是模式中沒有捕獲組,則該數組只包含一項)
  • 0530、正則表達式的第二個方法是 test() ,它接受一個字符串參數。在模式與該參數匹配的狀況下返回true ;不然,返回 false 。在只想知道目標字符串與某個模式是否匹配,但不須要知道其文本內容的狀況下,使用這個方法很是方便
  • 053一、正則表達式的 valueOf() 方法返回正則表達式自己。
  • 053二、即便 test() 方法只返回一個布爾值,但RegExp 構造函數的屬性$1和$2也會被匹配相應捕獲組的字符串自動填充
  • 053三、每一個函數都是Function類型的實例,並且都與其餘引用類型同樣具備屬性和方法。因爲函數是對象,所以函數名實際上也是一個指向函數對象的指針,不會與某個函數綁定
  • 053四、Function構造函數能夠接收任意數量的參數,但最後一個參數始終都被當作是函數體,而前面的參數則枚舉出了新函數的參數。可是,咱們不推薦讀者使用這種方法定義函數,由於這種語法會致使解析兩次代碼(第一次是解析常規 ECMAScript代碼,第二次是解析傳入構造函數中的字符串),從而影響性能
  • 053五、函數聲明式與函數表達式的區別。解析器在向執行環境中加載數據時,對函數聲明和函數表達式並不是一視同仁。解析器會率先讀取函數聲明,並使其在執行任何代碼以前可用(能夠訪問);至於函數表達式,則必須等到解析器執行到它所在的代碼行,纔會真正被解釋執行
  • 053六、由於 ECMAScript中的函數名自己就是變量,因此函數也能夠做爲值來使用。也就是說,不只能夠像傳遞參數同樣把一個函數傳遞給另外一個函數,並且能夠將一個函數做爲另外一個函數的結果返回
  • 053七、arguments是一個類數組對象,包含着傳入函數中的全部參數。雖然 arguments 的主要用途是保存函數參數,但這個對象還有一個名叫 callee 的屬性,該屬性是一個指針,指向擁有這個 arguments 對象的函數
  • 053八、this引用的是函數據以執行的環境對象——或者也能夠說是this值(當在網頁的全局做用域中調用函數時,this對象引用的就是window)
  • 053九、函數的名字僅僅是一個包含指針的變量而已。所以,即便是在不一樣的環境中執行,全局的 sayColor() 函數與 o.sayColor() 指向的仍然是同一個函數
  • 0540、ECMAScript5也規範化了另外一個函數對象的屬性: caller 。除了Opera的早期版本不支持,其餘瀏覽器都支持這個 ECMAScript3並無定義的屬性。這個屬性中保存着調用當前函數的函數的引用,若是是在全局做用域中調用當前函數,它的值爲null。爲了實現更鬆散的耦合,也能夠經過 arguments.callee.caller來訪問相同的信息
  • 054一、IE、Firefox、Chrome和Safari的全部版本以及 Opera 9.6 都支持 caller 屬性
  • 054二、當函數在嚴格模式下運行時,訪問arguments.callee 會致使錯誤。ECMAScript5還定義了arguments.caller 屬性,但在嚴格模式下訪問它也會致使錯誤,而在非嚴格模式下這個屬性始終是undefined。定義這個屬性是爲了分清 arguments.caller和函數的caller屬性。以上變化都是爲了增強這門語言的安全性,這樣第三方代碼就不能在相同的環境裏窺視其餘代碼了
  • 054三、ECMAScript中的函數是對象,所以函數也有屬性和方法。每一個函數都包含兩個屬性: length和prototype 。其中,length屬性表示函數但願接收的命名參數的個數
  • 054四、在ECMAScript5中,prototype屬性是不可枚舉的,所以使用 for-in 沒法發現
  • 054五、每一個函數都包含兩個非繼承而來的方法:apply() 和 call() 。這兩個方法的用途都是在特定的做用域中調用函數,實際上等於設置函數體內this對象的值。首先, apply() 方法接收兩個參數:一個是在其中運行函數的做用域,另外一個是參數數組。其中,第二個參數能夠是Array 的實例,也能夠是arguments 對象
  • 054六、在嚴格模式下,未指定環境對象而調用函數,則 this 值不會轉型爲 window 。除非明確把函數添加到某個對象或者調用 apply() 或 call() ,不然 this 值將是undefined
  • 054七、call()方法與apply()方法的做用相同,它們的區別僅在於接收參數的方式不一樣。對於call()方法而言,第一個參數是 this值沒有變化,變化的是其他參數都直接傳遞給函數。換句話說,在使用call()方法時,傳遞給函數的參數必須逐個列舉出來
  • 054八、事實上,傳遞參數並不是 apply() 和 call() 真正的用武之地;它們真正強大的地方是可以擴充函數賴以運行的做用域
  • 054九、使用 call()(或apply())來擴充做用域的最大好處,就是對象不須要與方法有任何耦合關係
  • 0550、ECMAScript 5 還定義了一個方法: bind() 。這個方法會建立一個函數的實例,其 this 值會被綁定到傳給 bind() 函數的值。支持 bind() 方法的瀏覽器有 IE9+、Firefox 4+、Safari 5.1+、Opera 12+和 Chrome
  • 055一、爲了便於操做基本類型值,ECMAScript還提供了 3 個特殊的引用類型:Boolean、Number和String。這些類型與本章介紹的其餘引用類型類似,但同時也具備與各自的基本類型相應的特殊行爲。實際上,每當讀取一個基本類型值的時候,後臺就會建立一個對應的基本包裝類型的對象,從而讓咱們可以調用一些方法來操做這些數據
  • 055二、引用類型與基本包裝類型的主要區別就是對象的生存期。使用 new操做符建立的引用類型的實例,在執行流離開當前做用域以前都一直保存在內存中。而自動建立的基本包裝類型的對象,則只存在於一行代碼的執行瞬間,而後當即被銷燬。這意味着咱們不能在運行時爲基本類型值添加屬性和方法
  • 055三、Object構造函數也會像工廠方法同樣,根據傳入值的類型返回相應基本包裝類型的實例。var obj = new Object("some text"); alert(obj instanceof String); //true
  • 055四、使用new調用基本包裝類型的構造函數,與直接調用同名的轉型函數是不同的
  • 055五、 toFixed()方法會按照指定的小數位返回數值的字符串表示。若是數值自己包含的小數位比指定的還多,那麼接近指定的最大小數位的值就會舍入。能夠利用round配合toFixed加爵該方法的在ie瀏覽器上的兼容問題
  • 055六、對於一個數值來講,toPrecision()方法可能會返回固定大小(fixed)格式,也可能返回指數(exponential)格式;具體規則是看哪一種格式最合適。這個方法接收一個參數,即表示數值的全部數字的位數(不包括指數部分)。實際上,toPrecision()會根據要處理的數值決定究竟是調用 toFixed() 仍是調用 toExponential()
  • 055七、在使用typeof操做符測試基本類型數值時,始終會返回 "number" ,而在測試 Number 對象時,則會返回 "object" 。相似地,Number對象是Number類型的實例,而基本類型的數值則不是
  • 055八、兩個用於訪問字符串中特定字符的方法是:charAt() 和 charCodeAt()。這兩個方法都接收一個參數,即基於 0 的字符位置。其中,charAt()方法以單字符字符串的形式返回給定位置的那個字符(ECMAScript中沒有字符類型)
  • 055九、ECMAScript5還定義了另外一個訪問個別字符的方法。在支持此方法的瀏覽器中,可使用方括號加數字索引來訪問字符串中的特定字符。使用方括號表示法訪問個別字符的語法獲得了 IE8 及 Firefox、Safari、Chrome 和 Opera 全部版本的支持。若是是在IE7及更早版本中使用這種語法,會返回undefined值(儘管根本不是特殊的undefined 值)
  • 0560、ECMAScript還提供了三個基於子字符串建立新字符串的方法: slice() 、 substr() 和 substring() 。這三個方法都會返回被操做字符串的一個子字符串,並且也都接受一或兩個參數。第一個參數指定子字符串的開始位置,第二個參數(在指定的狀況下)表示子字符串到哪裏結束。具體來講, slice() 和substring() 的第二個參數指定的是子字符串最後一個字符後面的位置。而 substr() 的第二個參數指定的則是返回的字符個數。若是沒有給這些方法傳遞第二個參數,則將字符串的長度做爲結束位置。與concat() 方法同樣, slice() 、 substr() 和 substring() 也不會修改字符串自己的值——它們只是返回一個基本類型的字符串值,對原始字符串沒有任何影響。在傳遞給這些方法的參數是負值的狀況下,它們的行爲就不盡相同了。其中, slice() 方法會將傳入的負值與字符串的長度相加, substr() 方法將負的第一個參數加上字符串的長度,而將負的第二個參數轉換爲 0。最後, substring() 方法會把全部負值參數都轉換爲 0
  • 056一、IE 的 JavaScript 實如今處理向 substr() 方法傳遞負值的狀況時存在問題,它會返回原始的字符串。IE9 修復了這個問題
  • 056二、有兩個能夠從字符串中查找子字符串的方法: indexOf() 和 lastIndexOf() 。這兩個方法都是從一個字符串中搜索給定的子字符串,而後返子字符串的位置(若是沒有找到該子字符串,則返回 -1 )。這兩個方法的區別在於: indexOf() 方法從字符串的開頭向後搜索子字符串,而 lastIndexOf() 方法是從字符串的末尾向前搜索子字符串。這兩個方法均可以接收可選的第二個參數,表示從字符串中的哪一個位置開始搜索
  • 056三、ECMAScript 5 爲全部字符串定義了 trim() 方法。這個方法會建立一個字符串的副本,刪除前置及後綴的全部空格,而後返回結果。因爲 trim() 返回的是字符串的副本,因此原始字符串中的前置及後綴空格會保持不變。支持這個方法的瀏覽器有 IE9+、Firefox 3.5+、Safari 5+、Opera 10.5+和 Chrome。此外,Firefox 3.5+、Safari 5+和 Chrome 8+還支持非標準的 trimLeft() 和 trimRight() 方法,分別用於刪除字符串開頭和末尾的空格
  • 056四、接下來咱們要介紹的是一組與大小寫轉換有關的方法。ECMAScript中涉及字符串大小寫轉換的方法有 4 個:toLowerCase()、toLocaleLowerCase()、toUpperCase()和 toLocaleUpperCase() 。其中, toLowerCase() 和 toUpperCase() 是兩個經典的方法,借鑑自 java.lang.String 中的同名方法。而 toLocaleLowerCase() 和 toLocaleUpperCase() 方法則是針對特定地區的實現。通常來講,在不知道本身的代碼將在哪一種語言環境中運行的狀況下,仍是使用針對地區的方法更穩妥一些
  • 056五、String 類型定義了幾個用於在字符串中匹配模式的方法。第一個方法就是 match() ,在字符串上調用這個方法,本質上與調用 RegExp 的 exec() 方法相同。 match() 方法只接受一個參數,要麼是一個正則表達式,要麼是一個 RegExp 對象
  • 056六、另外一個用於查找模式的方法是 search() 。這個方法的惟一參數與 match() 方法的參數相同:由字符串或 RegExp 對象指定的一個正則表達式。 search() 方法返回字符串中第一個匹配項的索引;若是沒有找到匹配項,則返回 -1 。並且, search() 方法始終是從字符串開頭向後查找模式
  • 056七、ECMAScript 提供了 replace() 方法。這個方法接受兩個參數:第一個參數能夠是一個 RegExp 對象或者一個字符串(這個字符串不會被轉換成正則表達式),第二個參數能夠是一個字符串或者一個函數。若是第一個參數是字符串,那麼只會替換第一個子字符串。要想替換全部子字符串,惟一的辦法就是提供一個正則表達式,並且要指定全局( g )標誌
  • 056八、replace() 方法的第二個參數也能夠是一個函數。在只有一個匹配項(即與模式匹配的字符串)的狀況下,會向這個函數傳遞 3 個參數:模式的匹配項、模式匹配項在字符串中的位置和原始字符串。在正則表達式中定義了多個捕獲組的狀況下,傳遞給函數的參數依次是模式的匹配項、第一個捕獲組的匹配項、第二個捕獲組的匹配項……,但最後兩個參數仍然分別是模式的匹配項在字符串中的位置和原始字符串。這個函數應該返回一個字符串,表示應該被替換的匹配項使用函數做爲 replace() 方法的第二個參數能夠實現更加精細的替換操做
  • 056九、最後一個與模式匹配有關的方法是 split() ,這個方法能夠基於指定的分隔符將一個字符串分割成多個子字符串,並將結果放在一個數組中。分隔符能夠是字符串,也能夠是一個 RegExp 對象(這個方法不會將字符串當作正則表達式)。 split() 方法能夠接受可選的第二個參數,用於指定數組的大小,以便確保返回的數組不會超過既定大小。對 split() 中正則表達式的支持因瀏覽器而異。儘管對於簡單的模式沒有什麼差異,但對於未發現匹配項以及帶有捕獲組的模式,匹配的行爲就不大相同了
  • 0570、與操做字符串有關的最後一個方法是 localeCompare() ,這個方法比較兩個字符串,並返回下列值中的一個: 若是字符串在字母表中應該排在字符串參數以前,則返回一個負數(大多數狀況下是 -1 ,具體的值要視實現而定); 若是字符串等於字符串參數,則返回 0 ;若是字符串在字母表中應該排在字符串參數以後,則返回一個正數(大多數狀況下是 1 ,具體的值一樣要視實現而定)。localeCompare() 方法比較不同凡響的地方,就是實現所支持的地區(國家和語言)決定了這個方法的行爲
  • 057一、另外, String 構造函數自己還有一個靜態方法: fromCharCode() 。這個方法的任務是接收一或多個字符編碼,而後將它們轉換成一個字符串。從本質上來看,這個方法與實例方法 charCodeAt()執行的是相反的操做
  • 057二、 encodeURI() 主要用於整個 URI(例如,http://www.wrox.com/illegal value.htm),而 encode-URIComponent() 主要用於對 URI 中的某一段(例如前面 URI 中的 illegal value.htm )進行編碼。它們的主要區別在於, encodeURI() 不會對自己屬於 URI 的特殊字符進行編碼,例如冒號、正斜槓、問號和井字號;而 encodeURIComponent() 則會對它發現的任何非標準字符進行編碼
  • 057三、一 般 來 說 , 我 們 使 用 encodeURIComponent() 方 法 的 時 候 要 比 使 用encodeURI() 更多,由於在實踐中更常見的是對查詢字符串參數而不是對基礎 URI進行編碼。
  • 057四、與 encodeURI() 和 encodeURIComponent() 方法對應的兩個方法分別是 decodeURI() 和decodeURIComponent()
  • 057五、如今,咱們介紹最後一個——大概也是整個 ECMAScript語言中最強大的一個方法: eval() 。 eval()方法就像是一個完整的 ECMAScript 解析器,它只接受一個參數,即要執行的 ECMAScript (或 JavaScript)字符串
  • 057六、可以解釋代碼字符串的能力很是強大,但也很是危險。所以在使用 eval() 時必須極爲謹慎,特別是在用它執行用戶輸入數據的狀況下。不然,可能會有惡意用戶輸入威脅你的站點或應用程序安全的代碼(即所謂的代碼注入)
  • 057七、其中, min() 和 max() 方法用於肯定一組數值中的最小值和最大值。這兩個方法均可以接收任意多個數值參數
  • 057八、要找到數組中的最大或最小值,能夠像下面這樣使用 apply() 方法。Math.max.apply(Math,[1,2,4,65,8,4)//65
  • 057九、下面來介紹將小數值舍入爲整數的幾個方法: Math.ceil() 、 Math.floor() 和 Math.round()
  • 0580、Math.random() 方法返回大於等於 0 小於 1 的一個隨機數
  • 058一、 引用類型與傳統面向對象程序設計中的類類似,但實現不一樣
  • 058二、Object 是一個基礎類型,其餘全部類型都從 Object 繼承了基本的行爲
  • 058三、Array 類型是一組值的有序列表,同時還提供了操做和轉換這些值的功能
  • 058四、Date 類型提供了有關日期和時間的信息,包括當前日期和時間以及相關的計算功能
  • 058五、RegExp 類型是 ECMAScript 支持正則表達式的一個接口,提供了最基本的和一些高級的正則表達式功能
  • 058六、函數其實是 Function 類型的實例,所以函數也是對象;而這一點正是 JavaScript 最有特點的地方。因爲函數是對象,因此函數也擁有方法,能夠用來加強其行爲
  • 058七、由於有了基本包裝類型,因此 JavaScript 中的基本類型值能夠被看成對象來訪問。三種基本包裝類型分別是: Boolean 、 Number 和 String 。如下是它們共同的特徵
  • 058八、在全部代碼執行以前,做用域中就已經存在兩個內置對象: Global 和 Math 。在大多數 ECMAScript實現中都不能直接訪問 Global 對象;不過,Web 瀏覽器實現了承擔該角色的 window 對象。全局變量和函數都是 Global 對象的屬性。 Math 對象提供了不少屬性和方法,用於輔助完成複雜的數學計算任務

第六章、面向對象的程序設計

  • 060一、ECMAScript中有兩種屬性:數據屬性和訪問器屬性。數據屬性包含一個數據值的位置。在這個位置能夠讀取和寫入值。數據屬性有4個描述其行爲的特性。對於像前面例子中那樣直接在對象上定義的屬性,它們的[[Configurable]] 、[[Enumerable]]和[[Writable]]特性都被設置爲 true ,而[[Value]]特性被設置爲指定的值。要修改屬性默認的特性,必須使用ECMAScript5的Object.defineProperty()方法。這個方法接收三個參數:屬性所在的對象、屬性的名字和一個描述符對象。其中,描述符(descriptor)對象的屬性必須是:configurable、enumerable 、 writable和value。設置其中的一或多個值,能夠修改對應的特性值。能夠屢次調用Object.defineProperty() 方法修改同一個屬性,但在把configurable特性設置爲 false 以後就會有限制了。在調用Object.defineProperty() 方法時,若是不指定,configurable、enumerable 和writable特性的默認值都是false。多數狀況下,可能都沒有必要利用Object.defineProperty()方法提供的這些高級功能
  • 060二、訪問器屬性不包含數據值;它們包含一對兒getter 和 setter函數(不過,這兩個函數都不是必需的)。在讀取訪問器屬性時,會調用getter函數,這個函數負責返回有效的值;在寫入訪問器屬性時,會調用setter函數並傳入新值,這個函數負責決定如何處理數據。訪問器屬性有以下 4 個特性:[[Configurable]]、[[Enumerable]]、[[Get]]、[[Set]]
  • 060三、在不支持Object.defineProperty()方法的瀏覽器中不能修改[[Configurable]]和[[Enumerable]]
  • 060四、支持 Object.defineProperties()方法的瀏覽器有 IE9+、Firefox 4+、Safari 5+、Opera 12+和Chrome
  • 060五、在 JavaScript 中,能夠針對任何對象——包括 DOM 和 BOM 對象,使用 Object.getOwnProperty-Descriptor() 方法。支持這個方法的瀏覽器有 IE9+、Firefox 4+、Safari 5+、Opera 12+和 Chrome
  • 060六、工廠模式是軟件工程領域一種廣爲人知的設計模式,這種模式抽象了建立具體對象的過程。工廠模式雖然解決了建立多個類似對象的問題,但卻沒有解決對象識別的問題(即怎樣知道一個對象的類型)
  • 060七、構造器模式。沒有顯式地建立對象;直接將屬性和方法賦給了 this 對象;沒有 return 語句。以這種方式調用構造函數實際上會經歷如下 4個步驟:建立一個新對象; 將構造函數的做用域賦給新對象(所以 this 就指向了這個新對象);執行構造函數中的代碼(爲這個新對象添加屬性);返回新對象。以這種方式定義的構造函數是定義在 Global 對象(在瀏覽器中是 window 對象)中的。使用構造函數的主要問題,就是每一個方法都要在每一個實例上從新建立一遍。在前面的例子中, person1 和 person2 都有一個名爲 sayName() 的方法,但那兩個方法不是同一個 Function 的實例
  • 060八、 prototype 就是經過調用構造函數而建立的那個對象實例的原型對象咱們建立的每一個函數都有一個 prototype (原型)屬性,這個屬性是一個指針,指向一個對象,而這個對象的用途是包含能夠由特定類型的全部實例共享的屬性和方法。使用原型對象的好處是可讓全部對象實例共享它所包含的屬性和方法。換句話說,沒必要在構造函數中定義對象實例的信息,而是能夠將這些信息直接添加到原型對象中
  • 060九、不管何時,只要建立了一個新函數,就會根據一組特定的規則爲該函數建立一個 prototype屬性,這個屬性指向函數的原型對象。在默認狀況下,全部原型對象都會自動得到一個 constructor(構造函數)屬性,這個屬性包含一個指向 prototype 屬性所在函數的指針
  • 06十、使用 Object.getPrototypeOf()能夠方便地取得一個對象的原型,而這在利用原型實現繼承(本章稍後會討論)的狀況下是很是重要的。支持這個方法的瀏覽器有 IE9+、Firefox 3.5+、Safari 5+、Opera 12+和 Chrome
  • 06十一、使用 delete 操做符則能夠徹底刪除實例屬性,從而讓咱們可以從新訪問原型中的屬性
  • 06十二、使用 hasOwnProperty() 方法能夠檢測一個屬性是存在於實例中,仍是存在於原型中。這個方法(不要忘了它是從 Object 繼承來的)只在給定屬性存在於對象實例中時,纔會返回 true
  • 061三、ECMAScript 5 的 Object.getOwnPropertyDescriptor() 方法只能用於實例屬性,要取得原型屬性的描述符,必須直接在原型對象上調用 Object.getOwnProperty-Descriptor() 方法
  • 061四、有兩種方式使用 in 操做符:單獨使用和在 for-in 循環中使用。在單獨使用時, in 操做符會在經過對象可以訪問給定屬性時返回true,不管該屬性存在於實例中仍是原型中
  • 061五、因爲 in 操做符只要經過對象可以訪問到屬性就返回 true , hasOwnProperty() 只在屬性存在於實例中時才返回 true ,所以只要 in 操做符返回 true 而 hasOwnProperty() 返回 false ,就能夠肯定屬性是原型中的屬性
  • 061六、要取得對象上全部可枚舉的實例屬性,可使用 ECMAScript 5 的 Object.keys() 方法。這個方法接收一個對象做爲參數,返回一個包含全部可枚舉屬性的字符串數組
  • 061七、若是你想要獲得全部實例屬性,不管它是否可枚舉,均可以使用 Object.getOwnPropertyNames()方法。 Object.keys() 和 Object.getOwnProperty-Names() 方法均可以用來替代 for-in 循環。支持這兩個方法的瀏覽器有 IE9+、Firefox 4+、Safari 5+、Opera12+和 Chrome
  • 061八、實例與原型之間的鏈接只不過是一個指針,而非一個副本,所以就能夠在原型中找到新的 sayHi 屬性並返回保存在那裏的函數
  • 061九、原型模式也不是沒有缺點。首先,它省略了爲構造函數傳遞初始化參數這一環節,結果全部實例在默認狀況下都將取得相同的屬性值。雖然這會在某種程度上帶來一些不方便,但還不是原型的最大問題。原型模式的最大問題是由其共享的本性所致使的
  • 0620、混合模式。建立自定義類型的最多見方式,就是組合使用構造函數模式與原型模式。構造函數模式用於定義實例屬性,而原型模式用於定義方法和共享的屬性。結果,每一個實例都會有本身的一份實例屬性的副本,但同時又共享着對方法的引用,最大限度地節省了內存。另外,這種混成模式還支持向構造函數傳遞參數;可謂是集兩種模式之長。這種構造函數與原型混成的模式,是目前在 ECMAScript中使用最普遍、認同度最高的一種建立自定義類型的方法。能夠說,這是用來定義引用類型的一種默認模式
  • 062一、使用動態原型模式時,不能使用對象字面量重寫原型。前面已經解釋過了,若是在已經建立了實例的狀況下重寫原型,那麼就會切斷現有實例與新原型之間的聯繫
  • 062二、關於寄生構造函數模式,有一點須要說明:首先,返回的對象與構造函數或者與構造函數的原型屬性之間沒有關係;也就是說,構造函數返回的對象與在構造函數外部建立的對象沒有什麼不一樣。爲此,不能依賴 instanceof 操做符來肯定對象類型。因爲存在上述問題,咱們建議在可使用其餘模式的狀況下,不要使用這種模式
  • 062三、繼承是 OO 語言中的一個最爲人津津樂道的概念。許多 OO 語言都支持兩種繼承方式:接口繼承和實現繼承。接口繼承只繼承方法簽名,而實現繼承則繼承實際的方法。如前所述,因爲函數沒有簽名,在 ECMAScript 中沒法實現接口繼承。ECMAScript 只支持實現繼承,並且其實現繼承主要是依靠原型鏈來實現的
  • 062四、構造函數、原型和實例的關係。每一個構造函數都有一個原型對象,原型對象都包含一個指向構造函數的指針,而實例都包含一個指向原型對象的內部指針
  • 062五、謹慎地定義方法。子類型有時候須要重寫超類型中的某個方法,或者須要添加超類型中不存在的某個方法。但無論怎樣,給原型添加方法的代碼必定要放在替換原型的語句以後
  • 062六、經過原型鏈實現繼承時,不能使用對象字面量建立原型方法。由於這樣作就會重寫原型鏈
  • 062七、在解決原型中包含引用類型值所帶來問題的過程當中,開發人員開始使用一種叫作借用構造函數(constructor stealing)的技術(有時候也叫作僞造對象或經典繼承)。這種技術的基本思想至關簡單,即在子類型構造函數的內部調用超類型構造函數。別忘了,函數只不過是在特定環境中執行代碼的對象,所以經過使用 apply() 和 call() 方法也能夠在(未來)新建立的對象上執行構造函數
  • 062八、相對於原型鏈而言,借用構造函數有一個很大的優點,便可以在子類型構造函數中向超類型構造函數傳遞參數
  • 062九、若是僅僅是借用構造函數,那麼也將沒法避免構造函數模式存在的問題——方法都在構造函數中定義,所以函數複用就無從談起了。並且,在超類型的原型中定義的方法,對子類型而言也是不可見的,結果全部類型都只能使用構造函數模式。考慮到這些問題,借用構造函數的技術也是不多單獨使用的
  • 0630、ECMAScript 5 經過新增 Object.create() 方法規範化了原型式繼承。這個方法接收兩個參數:一個用做新對象原型的對象和(可選的)一個爲新對象定義額外屬性的對象。在傳入一個參數的狀況下,Object.create() 與 object() 方法的行爲相同。Object.create() 方法的第二個參數與 Object.defineProperties() 方法的第二個參數格式相同:每一個屬性都是經過本身的描述符定義的。以這種方式指定的任何屬性都會覆蓋原型對象上的同名屬性
  • 063一、寄生組合式繼承,即經過借用構造函數來繼承屬性,經過原型鏈的混成形式來繼承方法
  • 063二、 工廠模式,使用簡單的函數建立對象,爲對象添加屬性和方法,而後返回對象。這個模式後來被構造函數模式所取代
  • 063三、 構造函數模式,能夠建立自定義引用類型,能夠像建立內置對象實例同樣使用 new 操做符。不過,構造函數模式也有缺點,即它的每一個成員都沒法獲得複用,包括函數。因爲函數能夠不侷限於任何對象(即與對象具備鬆散耦合的特色),所以沒有理由不在多個對象間共享函數
  • 063四、原型模式,使用構造函數的 prototype 屬性來指定那些應該共享的屬性和方法。組合使用構造函數模式和原型模式時,使用構造函數定義實例屬性,而使用原型定義共享的屬性和方法
  • 063五、JavaScript 主要經過原型鏈實現繼承。原型鏈的構建是經過將一個類型的實例賦值給另外一個構造函數的原型實現的。這樣,子類型就可以訪問超類型的全部屬性和方法,這一點與基於類的繼承很類似。原型鏈的問題是對象實例共享全部繼承的屬性和方法,所以不適宜單獨使用。解決這個問題的技術是借用構造函數,即在子類型構造函數的內部調用超類型構造函數。這樣就能夠作到每一個實例都具備本身的屬性,同時還能保證只使用構造函數模式來定義類型。使用最多的繼承模式是組合繼承,這種模式使用原型鏈繼承共享的屬性和方法,而經過借用構造函數繼承實例屬性。 寄生組合式繼承,集寄生式繼承和組合繼承的優勢與一身,是實現基於類型繼承的最有效方式
  • 063六、當某個函數被調用時,會建立一個執行環境(execution context)及相應的做用域鏈。而後,使用 arguments 和其餘命名參數的值來初始化函數的活動對象(activation object)。但在做用域鏈中,外部函數的活動對象始終處於第二位,外部函數的外部函數的活動對象處於第三位,……直至做爲做用域鏈終點的全局執行環境

第七章 函數表達式

  • 070一、因爲閉包會攜帶包含它的函數的做用域,所以會比其餘函數佔用更多的內存。過分使用閉包可能會致使內存佔用過多,咱們建議讀者只在絕對必要時再考慮使用閉包。雖然像 V8 等優化後的 JavaScript 引擎會嘗試回收被閉包占用的內存,但請你們仍是要慎重使用閉包
  • 070二、在閉包中使用 this 對象也可能會致使一些問題。咱們知道, this 對象是在運行時基於函數的執行環境綁定的:在全局函數中, this 等於 window ,而當函數被做爲某個對象的方法調用時, this 等於那個對象。不過,匿名函數的執行環境具備全局性,所以其 this 對象一般指向window。但有時候因爲編寫閉包的方式不一樣,這一點可能不會那麼明顯
  • 070三、若是閉包的做用域鏈中保存着一個HTML 元素,那麼就意味着該元素將沒法被銷燬
  • 070四、閉包會引用包含函數的整個活動對象,而其中包含着 element 。即便閉包不直接引用 element ,包含函數的活動對象中也仍然會保存一個引用。所以,有必要把 element 變量設置爲 null 。這樣就可以解除對 DOM 對象的引用,順利地減小其引用數,確保正常回收其佔用的內存
  • 070五、函數聲明後面不能跟圓括號。然而,函數表達式的後面能夠跟圓括號。要將函數聲明轉換成函數表達式,只要像下面這樣給它加上一對圓括號便可
  • 070六、通常來講,咱們都應該儘可能少向全局做用域中添加變量和函數。在一個由不少開發人員共同參與的大型應用程序中,過多的全局變量和函數很容易致使命名衝突。而經過建立私有做用域,每一個開發人員既可使用本身的變量,又沒必要擔憂搞亂全局做用域
  • 070七、嚴格來說,JavaScript 中沒有私有成員的概念;全部對象屬性都是公有的。不過,卻是有一個私有變量的概念。任何在函數中定義的變量,均可以認爲是私有變量,由於不能在函數的外部訪問這些變量。私有變量包括函數的參數、局部變量和在函數內部定義的其餘函數。
  • 070八、構造函數模式的缺點是針對每一個實例都會建立一樣一組新方法,而使用靜態私有變量來實現特權方法就能夠避免這個問題
  • 070九、初始化未經聲明的變量,老是會建立一個全局變量
  • 07十、多查找做用域鏈中的一個層次,就會在必定程度上影響查找速度。而這正是使用閉包和私有變量的一個顯明的不足之處
  • 07十一、 函數表達式不一樣於函數聲明。函數聲明要求有名字,但函數表達式不須要。沒有名字的函數表達式也叫作匿名函數
  • 07十二、在沒法肯定如何引用函數的狀況下,遞歸函數就會變得比較複雜
  • 071三、 遞歸函數應該始終使用 arguments.callee 來遞歸地調用自身,不要使用函數名——函數名可能會發生變化
  • 071四、當在函數內部定義了其餘函數時,就建立了閉包。閉包有權訪問包含函數內部的全部變量:在後臺執行環境中,閉包的做用域鏈包含着它本身的做用域、包含函數的做用域和全局做用域;一般,函數的做用域及其全部變量都會在函數執行結束後被銷燬;可是,當函數返回了一個閉包時,這個函數的做用域將會一直在內存中保存到閉包不存在爲止
  • 071五、使用閉包能夠在 JavaScript中模仿塊級做用域(JavaScript自己沒有塊級做用域的概念)
  • 071六、JavaScript 中的函數表達式和閉包都是極其有用的特性,利用它們能夠實現不少功能。不過,由於建立閉包必須維護額外的做用域,因此過分使用它們可能會佔用大量內存

第八章 BOM

  • 080一、拋開全局變量會成爲 window 對象的屬性不談,定義全局變量與在 window 對象上直接定義屬性仍是有一點差異:全局變量不能經過 delete 操做符刪除,而直接在 window 對象上的定義的屬性能夠
  • 080二、剛纔使用 var 語句添加的 window 屬性有一個名爲 [[Configurable]] 的特性,這個特性的值被設置爲 false ,所以這樣定義的屬性不能夠經過 delete 操做符刪除。IE8及更早版本在遇到使用 delete刪除 window 屬性的語句時,無論該屬性最初是如何建立的,都會拋出錯誤,以示警告。IE9 及更高版本不會拋出錯誤
  • 080三、嘗試訪問未聲明的變量會拋出錯誤,可是經過查詢 window 對象,能夠知道某個可能未聲明的變量是否存在20二、窗口位置。用來肯定和修改 window 對象位置的屬性和方法有不少。IE、Safari、Opera 和 Chrome 都提供了screenLeft 和 screenTop 屬性,分別用於表示窗口相對於屏幕左邊和上邊的位置。Firefox 則在screenX 和 screenY 屬性中提供相同的窗口位置信息,Safari 和 Chrome 也同時支持這兩個屬性。Opera雖然也支持 screenX 和 screenY 屬性,但與 screenLeft 和 screenTop 屬性並不對應,所以建議你們不要在 Opera 中使用它們
  • 080四、最終結果,就是沒法在跨瀏覽器的條件下取得窗口左邊和上邊的精確座標值。然而,使用 moveTo()和 moveBy() 方法卻是有可能將窗口精確地移動到一個新位置。這兩個方法都接收兩個參數,其中moveTo() 接收的是新位置的 x 和 y 座標值,而 moveBy() 接收的是在水平和垂直方向上移動的像素數。
  • 080五、須要注意的是,這兩個方法可能會被瀏覽器禁用;並且,在 Opera 和 IE 7(及更高版本)中默認就是禁用的。另外,這兩個方法都不適用於框架,只能對最外層的 window 對象使用
  • 080六、跨瀏覽器肯定一個窗口的大小不是一件簡單的事。IE9+、Firefox、Safari、Opera 和 Chrome 均爲此提供了 4個屬性: innerWidth、 innerHeight 、 outerWidth 和 outerHeight 。在 IE9+、Safari和 Firefox中, outerWidth 和 outerHeight 返回瀏覽器窗口自己的尺寸(不管是從最外層的 window 對象仍是從某個框架訪問)。在Opera中,這兩個屬性的值表示頁面視圖容器① 的大小。而innerWidth 和 innerHeight則表示該容器中頁面視圖區的大小(減去邊框寬度)。在 Chrome 中, outerWidth 、 outerHeight 與innerWidth 、 innerHeight 返回相同的值,即視口(viewport)大小而非瀏覽器窗口大小
  • 080七、在 IE、Firefox、Safari、Opera 和 Chrome 中, document.documentElement.clientWidth 和document.documentElement.clientHeight 中保存了頁面視口的信息。在 IE6 中,這些屬性必須在標準模式下才有效;若是是混雜模式,就必須經過 document.body.clientWidth 和 document.body.clientHeight 取得相同信息。而對於混雜模式下的 Chrome,則不管經過 document.documentEle-ment 仍是 document.body 中的 clientWidth 和 clientHeight 屬性,均可以取得視口的大小
  • 080八、對於移動設備, window.innerWidth 和 window.innerHeight 保存着可見視口,也就是屏幕上可見頁面區域的大小。移動 IE 瀏覽器不支持這些屬性,但經過 document.documentElement.client-Width 和 document.documentElement.clientHeihgt 提供了相同的信息。隨着頁面的縮放,這些值也會相應變化
  • 080九、有關移動設備視口的話題比較複雜,有不少很是規的情形,也有各類各樣的建議。移動開發諮詢師 Peter-Paul Koch 記述了他對這個問題的研究:http://t.cn/zOZs0Tz。若是你在作移動 Web 開發,推薦你讀一讀這篇文章
  • 08十、 window.open() 方法既能夠導航到一個特定的 URL,也能夠打開一個新的瀏覽器窗口。這個方法能夠接收 4 個參數:要加載的 URL、窗口目標、一個特性字符串以及一個表示新頁面是否取代瀏覽器歷史記錄中當前加載頁面的布爾值。一般只須傳遞第一個參數,最後一個參數只在不打開新窗口的狀況下使用。後面這行代碼會打開一個新的能夠調整大小的窗口,窗口初始大小爲 400×400 像素,而且距屏幕上沿和左邊各 10 像素。window.open("http://www.wrox.com/","wroxWindow","height=400,width=400,top=10,left=10,resizable=yes");
  • 08十一、wroxWin.close()這個方法僅適用於經過 window.open() 打開的彈出窗口。對於瀏覽器的主窗口,若是沒有獲得用戶的容許是不能關閉它的。不過,彈出窗口卻是能夠調用 top.close() 在不經用戶容許的狀況下關閉本身。彈出窗口關閉以後,窗口的引用仍然還在,但除了像下面這樣檢測其 closed 屬性以外,已經沒有其餘用處了
  • 08十二、超時調用須要使用 window 對象的 setTimeout() 方法,它接受兩個參數:要執行的代碼和以毫秒錶示的時間(即在執行代碼前須要等待多少毫秒)。因爲傳遞字符串可能致使性能損失,所以不建議以字符串做爲第一個參數
  • 081三、JavaScript 是一個單線程序的解釋器,所以必定時間內只能執行一段代碼。爲了控制要執行的代碼,就有一個 JavaScript 任務隊列。這些任務會按照將它們添加到隊列的順序執行。 setTimeout() 的第二個參數告訴 JavaScript 再過多長時間把當前任務添加到隊列中。若是隊列是空的,那麼添加的代碼會當即執行;若是隊列不是空的,那麼它就要等前面的代碼執行完了之後再執行
  • 081四、超時調用的代碼都是在全局做用域中執行的,所以函數中 this 的值在非嚴格模式下指向 window 對象,在嚴格模式下是 undefined
  • 081五、通常認爲,使用超時調用來模擬間歇調用的是一種最佳模式。在開發環境下,不多使用真正的間歇調用,緣由是後一個間歇調用可能會在前一個間歇調用結束以前啓動。而像前面示例中那樣使用超時調用,則徹底能夠避免這一點。因此,最好不要使用間歇調用
  • 081六、經過 JavaScript 打開的對話框,即「查找」和「打印」。這兩個對話框都是異步顯示的,可以將控制權當即交還給腳本。這兩個對話框與用戶經過瀏覽器菜單的「查找」和「打印」命令打開的對話框相同。而在 JavaScript 中則能夠像下面這樣經過 window 對象的 find() 和 print() 方法打開它們
  • 081七、URL獲取參數並封裝成對象。這個函數的第一步是先去掉查詢字符串開頭的問號。固然,前提是 location.search 中必需要包含一或多個字符。而後,全部參數將被保存在 args 對象中,該對象以字面量形式建立。接下來,根據和號(&)來分割查詢字符串,並返回 name=value 格式的字符串數組。下面的 for 循環會迭代這個數組,而後再根據等於號分割每一項,從而返回第一項爲參數名,第二項爲參數值的數組。再使用 decodeURIComponent() 分別解碼 name 和 value (由於查詢字符串應該是被編碼過的)。最後,將 name 做爲 args 對象的屬性,將 value 做爲相應屬性的值
  • 081八、每次修改 location 的屬性( hash 除外),頁面都會以新 URL 從新加載
  • 081九、在 IE八、Firefox 一、Safari 2+、Opera 9+和 Chrome 中,修改 hash 的值會在瀏覽器的歷史記錄中生成一條新記錄。在 IE 的早期版本中, hash 屬性不會在用戶單擊「後退」和「前進」按鈕時被更新,而只會在用戶單擊包含 hash 的 URL 時纔會被更新
  • 0820、replace() 方法。這個方法只接受一個參數,即要導航到的 URL;結果雖然會致使瀏覽器位置改變,但不會在歷史記錄中生成新記錄。在調用 replace() 方法以後,用戶不能回到前一個頁面
  • 082一、與位置有關的最後一個方法是 reload() ,做用是從新加載當前顯示的頁面。若是調用 reload()時不傳遞任何參數,頁面就會以最有效的方式從新加載。也就是說,若是頁面自上次請求以來並無改變過,頁面就會從瀏覽器緩存中從新加載。若是要強制從服務器從新加載,則須要像下面這樣爲該方法傳遞參數 true。位於 reload() 調用以後的代碼可能會也可能不會執行,這要取決於網絡延遲或系統資源等因素。爲此,最好將 reload() 放在代碼的最後一行
  • 082二、檢測瀏覽器中是否安裝了特定的插件是一種最多見的檢測例程。對於非 IE 瀏覽器,可使用plugins 數組來達到這個目的。
  • 082三、檢測 IE 中的插件比較麻煩,由於 IE 不支持 Netscape 式的插件。在 IE 中檢測插件的惟一方式就是使用專有的 ActiveXObject 類型,並嘗試建立一個特定插件的實例。IE 是以 COM對象的方式實現插件的,而 COM對象使用惟一標識符來標識。所以,要想檢查特定的插件,就必須知道其 COM 標識符。例如,Flash 的標識符是 ShockwaveFlash.ShockwaveFlash
  • 082四、plugins 集合有一個名叫 refresh() 的方法,用於刷新 plugins 以反映最新安裝的插件。這個方法接收一個參數:表示是否應該從新加載頁面的一個布爾值。若是將這個值設置爲 true ,則會從新加載包含插件的全部頁面;不然,只更新 plugins集合,不從新加載頁面
  • 082五、history 對象保存着用戶上網的歷史記錄,從窗口被打開的那一刻算起。由於 history 是 window對象的屬性,所以每一個瀏覽器窗口、每一個標籤頁乃至每一個框架,都有本身的 history 對象與特定的window 對象關聯
  • 082六、使用 go() 方法能夠在用戶的歷史記錄中任意跳轉,能夠向後也能夠向前。這個方法接受一個參數,表示向後或向前跳轉的頁面數的一個整數值。負數表示向後跳轉(相似於單擊瀏覽器的「後退」按鈕),正數表示向前跳轉(相似於單擊瀏覽器的「前進」按鈕)。也能夠給 go() 方法傳遞一個字符串參數,此時瀏覽器會跳轉到歷史記錄中包含該字符串的第一個位置——可能後退,也可能前進,具體要看哪一個位置最近。若是歷史記錄中不包含該字符串,那麼這個方法什麼也不作
  • 082七、另外,還可使用兩個簡寫方法 back() 和 forward() 來代替 go() 。顧名思義,這兩個方法能夠模仿瀏覽器的「後退」和「前進」按鈕
  • 082八、當頁面的 URL 改變時,就會生成一條歷史記錄。在 IE8 及更高版本、Opera、Firefox、Safari 3 及更高版本以及 Chrome 中,這裏所說的改變包括 URL 中 hash 的變化(所以,設置 location.hash 會在這些瀏覽器中生成一條新的歷史記錄)
  • 082九、瀏覽器對象模型(BOM)以 window 對象爲依託,表示瀏覽器窗口以及頁面可見區域。同時, window對象仍是 ECMAScript 中的 Global 對象,於是全部全局變量和函數都是它的屬性,且全部原生的構造函數及其餘函數也都存在於它的命名空間下

第九章 客戶端檢測

  • 090一、檢測 Web 客戶端的手段不少,並且各有利弊。但最重要的仍是要知道,不到萬不得已,就不要使用客戶端檢測。只要能找到更通用的方法,就應該優先採用更通用的方法。一言以蔽之,先設計最通用的方案,而後再使用特定於瀏覽器的技術加強該方案
  • 090二、在實際開發中,應該將能力檢測做爲肯定下一步解決方案的依據,而不是用它來判斷用戶使用的是什麼瀏覽器
  • 090三、與能力檢測相似,怪癖檢測(quirks detection)的目標是識別瀏覽器的特殊行爲。但與能力檢測確認瀏覽器支持什麼能力不一樣,怪癖檢測是想要知道瀏覽器存在什麼缺陷(「怪癖」也就是 bug)
  • 090四、能力檢測:在編寫代碼以前先檢測特定瀏覽器的能力
  • 090五、 怪癖檢測:怪癖其實是瀏覽器實現中存在的 bug
  • 090六、用戶代理檢測:經過檢測用戶代理字符串來識別瀏覽器
  • 090七、在決定使用哪一種客戶端檢測方法時,通常應優先考慮使用能力檢測。怪癖檢測是肯定應該如何處理代碼的第二選擇。而用戶代理檢測則是客戶端檢測的最後一種方案,由於這種方法對用戶代理字符串具備很強的依賴性
相關文章
相關標籤/搜索