前端學習筆記Js篇(不定期更新)

注:沒有標註書名只有頁數的參考來源均指代《Javascript權威指南第六版》,其他參考均有書名或網址標註。
一、易產生誤區知識點記錄
1、[] == ! []
所有對象都轉化爲true(P52),數組是對象,因此空數組[]轉化爲布爾值爲真。而空數組轉化爲數字時爲0.因此左式Number([])=0。
“!”運算符首先將操作數轉換爲布爾值,然後再對布爾值求反(P81),因此右式爲!Boolean([])=!true=false
對於==,如果一個值是false,則將其轉化爲0再進行比較(p75)
因此以上等式爲0==0,結果爲true
這裏寫圖片描述
2、爲什麼說要避免使用eval()
eval() 是一個危險的函數, 他執行的代碼擁有着執行者的權利。如果你用 eval() 運行的字符串代碼被惡意方(不懷好意的人)操控修改,您最終可能會在您的網頁/擴展程序的權限下,在用戶計算機上運行惡意代碼。更重要的是,第三方代碼可以看到某一個eval()被調用時的作用域,這也有可能導致一些不同方式的攻擊。相似的 Function 就不容易被攻擊。
eval() 通常比替代方法慢,因爲它必須調用 JS 解釋器,而許多其他結構則由現代 JS 引擎進行優化。

3、數組索引既可以是數字也可以是字符
這裏寫圖片描述
對象是javascript的基本數據類型。對象是一種複合值。它將很多值(原始值 或者其他對象)聚合在一起。可通過名字訪問這些值。對象也可以看做是屬性的無序集合,每個屬性都有一個名/值。屬性名是字符串,因此我們可以把對象看成是從字符串到值的映射。 ( P118).數組是對象的頁數形式。使用方括號訪問數組元素就像用方括號訪問對象的屬性一樣。JavaScript將指定的數字索引值換成字符串——索引值1變成“1”(P146)

4、javascript:void(0)生效原理
void是一級運算符,它出現在操作數之前,操作數可以是任意類型。操作數會照常計算,但忽略計算結果並返回undefined(P89)
既然void會忽略計算結果返回undefined,那幹嘛不直接就寫undefined呢?答案很簡單,undefined 並不是保留詞(reserved word),它只是全局對象的一個屬性,在低版本 IE 中能被重寫。就算不在IE,也可以在局部作用域中被重寫。
這裏寫圖片描述
在url後面跟一個javascript:協議限定符,是另一種嵌入JavaScript代碼到客戶端的方式。這種特殊的協議類型指定URL內容爲任意字符串,這個字符串是會被JavaScript解釋器運行的JavaScript代碼,它被當成做單獨的一行代碼對待,這意味着語句之間必須用分號隔開,而註釋//必須用/* */替代。javascript:URL能識別的‘資源’是轉換成字符串執行代碼的返回值。如果代碼返回undefined,那麼這個資源是沒有內容的。javascript:URL可以用在可以使用常規URL的任意地方(P318)

5、如果數據屬性是不可配置的,則不能將他的可寫性從false改成true,但可以從true修改爲false

6、注意,一旦將對象轉換爲不可拓展的,就無法再將其轉換回可拓展的了。
對於那些已經封閉起來的對象是不能解封的。(P140)

7、判斷對象是否爲一個數組,及爲什麼instanceof操作符不能視爲一個可靠的的數組檢測方法的原因。
①、Object.prototype.toString.call(someval).slice(8,-1)判斷對象類型
對象的類屬性是一個字符串,用以表示對象的類型信息。

[object class]

因此想要獲得對象的類,可以調用對象的toString()方法,然後提取已返回字符串的第8個到倒數第二個位置的字符串。不過讓人感到棘手的是,很多對象繼承的toString()方法重寫了,爲了能調用正確的toString()版本,必須間接的調用Function.call()方法。(P139)

②在ECMAScript5中,可以使用Array.isArray()函數來檢測是否爲數組(P160)

③使用instanceof的問題是在Web瀏覽器中可能有多個窗口或窗體存在。每個窗口都有自己的javascript環境,有自己的全局對象。並且,每個全局對象有自己的一組構造函數。因此一個窗體中的對象將不可能是另外窗體中的構造函數的實例。窗體之間的混淆補償發生,但這個問題已經足以證明instanceof操作符不能視爲一個可靠的的數組檢測方法。(P161)

8、數組直接量的語法允許有可選的結尾的逗號,故[,]只有兩個元素而非三個

9、函數遞歸
如果一個函數定義表達式包含名稱,函數的局部作用域將會包含一個綁定到函數對象的名稱,實際上,函數的名稱將成爲函數內部的一個局部變量。通常而言,以表達式方式定義的函數都不需要名稱,這會讓定義它們的代碼更爲緊湊。(P167)
這裏寫圖片描述
如果函數聲明式不包含名稱,則使用參數對象的callee屬性來調用自身。在非嚴格模式下,ECMAScript標準規範規定callee屬性指代當前正在執行的函數。
這裏寫圖片描述

10、根據ECMAScript3和非嚴格的ECMAScript5對函數調用的規定,調用上下文(this)的值是全局對象。然而,在嚴格模式下,調用上下文是undefied。以函數形式調用的函數通常不使用this關鍵字。不過,this關鍵字可以用來判斷當前是嚴格模式。(P169)
方法調用和函數調用的一個重要的區別,即:調用上下文。屬性訪問表達式由兩個部分組成:一個對象和屬性名稱。在像這樣的函數表達式中(o.m),對象o成爲函數調用上下文。函數體可以使用關鍵字this調用該對象。(P170)

11、方法鏈:當方法的返回值是一個對象,這個對象還可以在調用它的方法。這種方法調用序列中(通常稱之爲’‘鏈’或者’級聯’)。每次的調用結果都是另外一個表達式的組成部分。當方法不需要返回值時,最好直接返回this,如果在設計的API中一直採用這種方式(每個方法都返回this),使用API就可以進行’鏈式調用’風格的編程,在這種編程風格中,只要指定一次要調用的對象即可,餘下的方法都可以基於此進行調用。(P171)

12、閉包原理
每次調用JavaScript函數的時候,都會爲之創建一個新的對象用來保存局部變量,把這個對象添加至作用域鏈中。當函數返回的時候,就從作用域鏈中將這個綁定變量的對象刪除。如果不存在嵌套的函數,也沒有其他引用指向這個綁定對象時,它就會被當做垃圾回收掉。如果定義了嵌套函數,每個嵌套函數都對應了一個作用域鏈,並且這個作用域鏈指向一個變量綁定對象。但如果這些嵌套的函數對象在外部被保存下來,那麼它們也會和所指向的變量綁定對象一樣當做垃圾回收。但是如果這個函數定義了嵌套的函數,並將它作爲返回值返回或者存儲在某處的屬性裏,這時就會有一個外部引用自己指向這個嵌套的函數。它就不會被當做垃圾回收,並且它所指向的變量綁定對象也不會被當做垃圾回收。(P184)
**作用域鏈:**作用域鏈是一個對象列表或者鏈表,這組對象定義了這段代碼’作用關於中’的變量。當javascript需要查找變量x的值得時候(變量解析),他會從鏈中的第一個對象開始查找,如果這個對象有一個名爲x的屬性,則會直接使用這個屬性的值,如果第一個對象中不存在名爲x的屬性,javascript會繼續查找鏈上的下一個對象。如果第二個對象依然沒有名爲x的屬性,則會繼續查找下一個對象,以此類推。如果作用域鏈上沒有任何一個對象含有屬性x,那麼久認爲這段代碼的作用域鏈上不存在x,並最終爆出一個引用錯誤異常。(P59)

13、理解原型
任何javascript函數都可以作爲構造函數(ECMAScript5中的Function.bind()返回的函數除外)都自動擁有一個prototype屬性。這個屬性的值是一個對象,這個對象包含唯一一個不可枚舉的屬性constructor。constructor屬性的值是一個函數對象。(P205)
無論什麼時候,只要創建了一個新的函數,就會根據一組特定的規則爲該函數創建一個prototype屬性,這個屬性指向函數的原型對象。在默認情況下,所有原型對象都會自動獲得一個constructor屬性,這個屬性是一個prototype屬性所在函數的指針。就拿前面的例子來說Person.prototype.construtor指向Person.而通過這個構造函數,我們還可以添加其他屬性和方法。
創建了自定義的構造函數之後,其原型對向默認只會取得constructor屬性;至於其他方法,則都是從Object繼承而來的。當調用構造函數創建一個新的實例後,該實例的內部將包含一個指針(內部屬性),指向構造函數的原型對象。ECMA-262第5版總管這個指針叫[[Prototype]].雖然在腳本中沒有標準的方式訪問[[Prototype]],但Firfox、Safair和Chrome在每個對象上的都支持一個屬性_—_proto_;而在其他市縣中,這個屬性對腳本則是完全不可見的。不過,要明確的真正重要的一點就是,這個連接存在於實例與構造函數的原型對象之間,而不是存在於實例與構造函數之間。(JavaScript高級程序設計第三版P148)

14、ECMAScript3規範規定,一個正則表達式直接量會在執行到它的時候轉換爲一個RegRxp對象,同一段代碼所表示正則表達式直接量的每次運算都返回同一個對象
ECMAScript5規範則做了相反的規定,同一段代碼多表示的正則表達式直接量的每次運算都返回新對象。(P254)

15、更改const聲明的簡單類型數據會報錯,而更改const聲明的符合數據類型可以成功。
const實際上保證的,並不是變量的值不得改動,而是變量指向的那個內存地址不得改動。對於簡單類型的數據(數值、字符串、布爾值),值就保存在變量指向的那個內存地址,因此等同於常量。但對於複合類型的數據(主要是對象和數組),變量指向的內存地址,保存的只是一個指針,const只能保證這個指針是固定的,至於它指向的數據結構是不是可變的,就完全不能控制了。
如果真的想將對象凍結,應該使用Object.freeze方法。(《ECMAScript 6 入門》作者:阮一峯)

二、要點總結
1、正則表達式
①字符類:將直接量字符串單獨放進方括號中就組成了字符類。一個字符類可以匹配他所包含的任意字符,因此,正則表達式/[a,b,c]/就就和字母’a’,‘b’,‘c’中的任意一個都匹配。另外,可以通過一個’‘字符來定義否定字符類,他匹配所有不包含在方括號內的字符,定義否定字符類時,將一個’‘符號作爲左方括號的第一個字符,正則表達式/[^abc]/匹配的是’a’,‘b’,'c’以外所有字符。(P256)
②重複:正則表達式的重複字符語法

字符 匹配
{n,m} 匹配前一項至少n次,但不能超過m次
{n,} 匹配前一項n次或者更多次
{n} 匹配前一項n次
? 匹配前一項0次或者一次
+ 匹配前一項一次或者多次
* 匹配前一項0次或者多次

③選擇:字符’|‘用於分割供選擇的字符。例如,/ab|cd|ef/可以匹配’ab’,‘cd’,‘ef’。注意選擇項的嘗試匹配順序是從左到右。
④分組:正則表達式中圓括號有多中作用,一個作用是把單獨的項組合成子表達式,以便可以像處理獨立單元那樣用’|’,’?’,’*’,’+‘等對單元內的項進行處理。
在正則表達式中,圓括號的另一個作用是在完整的模式中定義自模塊。當一個正則表達式成功地和目標字符串相匹配時,可以從目標穿中抽出和圓括號中的子模式相匹配的部分。
③引用:帶圓括號的表達式的另一個用途是允許在同一正則表達式的後部引用前面的子表達式。這是通過在字符’'後加一位或者多位數字實現的。這個數字指定了帶圓括號的字表達式,\3引用的是第三個帶圓括號的字表達式。注意,因爲字表達式可以嵌套另一個字表達式,所以它的位置是參與計數的左括號的位置。
④指定匹配位置
⑤修飾符

字符 含義
i 執行不區分大小寫的匹配
g 執行一個全局匹配,即找到所有匹配,而不是找到第一個之後就停止
m 多行匹配模式,^匹配一行的開頭和字符串的開頭,$匹配行的結束和字符串的結束

2、事件
①事件分類:

  • 依賴於設備的輸入事件:有些事件和特定的輸入設備直接相關,比如鼠標和鍵盤。
  • 獨立與設備的輸入事件:有些輸入事件沒有直接相關的特定輸入設備。比如click事件表示激活了連接、按鈕或其他文檔元素,者通常是用過鼠標單擊實現,但也能通過鍵盤或觸摸感知設備上的手勢來實現
  • 用戶界面事件:用戶界面事件是比較高級的事件,通常出現在定義web應用用戶界面的HTML表單元素上。包括文本輸入與獲取鍵盤焦點的focus時間、用戶改變表單元素顯示值的change時間和用戶單擊表單中的‘提交’按鈕的submit事件。
  • 狀態變化事件:有些時間不是有用戶活動而是有網絡或瀏覽器互動觸發,用來表示某種生命週期或相關狀態的變化。當文檔完全加載時,在Window對象上會發生load事件,這可能是這類事件中最常用的。
  • 特定api事件:HTML5及相關的規範定義的大量Web API都有自己的事件類型。拖放API。
  • 計時器和錯誤處理程序

②註冊事件處理程序

  • 設置JavaScript對象屬性爲事件處理程序:按照約定,事件處理程序屬性的名字由’on’後面跟着事件名組成。如onclick,onchange,onload,onmouseover等,注意這些屬性名是區分大小寫的,所有都是小寫,即是事件類型是多個詞組成(比如readstatechange)
  • 設置HTML標籤爲事件處理程序:用於設置的文檔元素事件處理程序屬性也能換成對應的HTML標籤的屬性,若如此做,屬性值應該是Javascript代碼字符串。這段代碼應該是處理程序的函數主體,而非完整的函數聲明。
  • addEventListener():addEventLisener()接受三個參數,第一個是要註冊處理程序的事件類型,這個事件類型是字符串,但它不應該包含用於設置事件處理程序屬性的前綴’on’。第二個參數是指定類型的事件發生時應該調用的函數。最後一個參數是布爾值,通常情況下,會給這個參數傳遞false。如果穿了truw,那麼函數將註冊爲補貨事件處理程 序,並在事件不同的調度階段調用
  • attachEvent():
    1>、因爲IE事件模型不支持事件捕獲,所以attachEvent()和detachEvent()要求只有兩個參數:事件類型和處理程序函數
    2>、IE方法的第一個參數使用了帶’on’前綴的事件處理程序屬性名,而非沒有前綴的事件類型。
    3>、attachEvent()允許相同的事件處理程序函數註冊很多次。當特定的事件發生時,註冊函數的調用次數和註冊次數一樣

3、XMLHttpRequest
①瀏覽器在XMLHttpRequest類上定義了它們的API。這個類的每個實力都表示一個獨立的請求/響應對,並且這個對象的屬性和方法允許指定請求細節和提取響應數據。
②你也許能重用已存在的XMLHttpRequest,但注意這將會終止之前通過該對象掛起的任何請求。(P487)
③一個HTTP請求由4部分組成:

  • HTTP請求方法或’動作’
  • 正在請求的URL
  • 一個可選的請求頭集合
  • 一個可選的請求主體

④服務器返回的HTTP響應包含三部分:

  • 一個數字和文本組成的狀態碼
  • 一個響應頭集合
  • 響應主體
    ⑤順序: HTTP請求的各部分有指定順序,請求方法和URL首先到達,然後是請求頭,最後是請求主體。
    ⑥取得響應
    • staus和stausText屬性以數字以和文本的形式返回HTTP狀態碼。這些屬性保存標準HTTP值。
    • 使用getResponseHeader()和getAllResponseHeader()能查詢響應頭。
    • 相應主體可以從responseText屬性中得到文本形式的,從responseXML屬性中得到Document形式的。
      ⑦爲了響應就緒得到通知,必須j監聽XMLHttpRequest對象上的readystatechange事件。爲了理解這個事件類型,你必須理解readystate屬性。readyState屬性是一個整數,它指定了HTTP的狀態
  • 0:open()尚未調用
  • 1:open()已調用
  • 2:接收到頭信息
  • 3:接收到相應主體
  • 4:響應完成

4、Web存儲: localStorage和sessionStorage的區別在於存儲的有效期和作用域不同。

  • ①localStorage存儲的數據時永久性的。sessionStorage的有效期則不同,一旦窗口或者標籤頁被永久關閉,那麼所有通過sessionStorage存儲的數據也都被刪除了
  • ②localStorage的作用域是限定在文檔源級別的。與localStorage一樣sessionStorage的作用域也是限定在文檔源中,不僅如此,sessionStorage的作用域還被限定在窗口中,如果同源的文檔渲染在不同的瀏覽器標籤頁中,那麼他們之間擁有的是各自的sessionStorage數據,無法共享。

5、HTMLAPI

①地理位置:navigator.geolocation
②歷史記錄管理

  • 哈希路由:利用location.hash和hashchange事件。hash屬性設置url的片段標識符,通常是用於指定滾動到的文檔中某一部分的ID。但是location.hash不一定要設置爲一個元素的ID:它可以設置爲任何字符串。如果能夠將應用狀態編碼成字符串,就可以使用該字符串作爲片段標識符。(p663)
  • history路由:利用history和pushState()方法和popstate事件。HTML5引入了 history.pushState() 和 history.replaceState() 方法,它們分別可以添加和修改歷史記錄條目。這些方法通常與window.onpopstate 配合使用。
    每當處於激活狀態的歷史記錄條目發生變化時,popstate事件就會在對應window對象上觸發. 如果當前處於激活狀態的歷史記錄條目是由history.pushState()方法創建,或者由history.replaceState()方法修改過的, 則popstate事件對象的state屬性包含了這個歷史記錄條目的state對象的一個拷貝.
    調用history.pushState()或者history.replaceState()不會觸發popstate事件.
    當網頁加載時,各瀏覽器對popstate事件是否觸發有不同的表現,Chrome 和 Safari會觸發popstate事件, 而Firefox不會.
    參考:https://developer.mozilla.org/zh-CN/docs/Web/API/History_API
    ③跨域消息傳遞
    ④Worker對象
    ⑤類型化數組和ArrayBuffer
    ⑥Blob
    ⑦文件系統API

三、學習心得
1、關於原型構造器的部分,感覺紅寶書比犀牛書的講解更加細緻,但是基礎部分的話犀牛書的解讀是非常清晰且容易理解的。
2、關於書中第18.3節(P508)的基於服務器推送事件的Comet事件,實踐後發現實際上是每過3s對服務器進行一次數據請求
3、在實踐postMessage時發現一個問題:
window.open()方法的返回打開窗口的引用,但是必須成功打開纔有引用返回,如果被瀏覽器攔截(出於安全性攔截非用戶點擊的窗口彈出)則返回null。

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