一. evalhtml
eval()函數計算JavaScript字符串,並把它做爲腳本代碼來執行。若是參數是一個表達式,eval()函數將執行表達式。若是參數是Javascript語句,eval()將執行Javascript語句。前端
圖1.1java
如上圖所示,第一個eval內部爲一個函數表達式,在執行該函數的同時,定義了兩個全局變量X和Y,因此結果分別爲200、4、27。數組
因爲由於它會執行任意傳給它的代碼,在代碼字符串未知或者是來自一個不信任的源時,會致使安全問題,同時很是耗性能(它會執行兩次2次,一次解析成js語句,一次執行),最重要的是,99.9%使用eval 的場景都有不使用eval的解決方案,因此在任何狀況下咱們都應該避免使用eval函數。瀏覽器
二. null與undefined 的區別緩存
(1) null表示一個對象是「沒有值」的值,也就是值爲「空」;undefined表示一個變量聲明瞭沒有初始化(即沒有賦值)。安全
(2) undefined不是一個有效的JSON,而null是;undefined的類型(typeof)是undefined,而null的類型(typeof)是object。閉包
(3) 在驗證null時,必定要使用「===」 ,由於「==」沒法分別null和undefined!app
圖2.1函數
三. 事件與事件流
(1) 事件
事件是文檔或者瀏覽器窗口中發生的,特定的交互瞬間,也能夠理解爲是用戶或瀏覽器自身執行的某種動做,如click,change和hover都是事件的名字,同時事件是javaScript和DOM之間交互的橋樑。
(2) 事件流
事件發生時會在元素節點與根節點之間按照特定的順序傳播,路徑所通過的全部節點都會收到該事件,這個傳播過程即DOM事件流。事件流有兩種模型,即捕獲型事件流和冒泡型事件流。
冒泡型事件流:事件的傳播是從最特定的事件目標到最不特定的事件目標。即從DOM樹的葉子到根。
捕獲型事件流:事件的傳播是從最不特定的事件目標到最特定的事件目標。即從DOM樹的根到葉子。
圖3.1
如上圖所示,DOM標準採用捕獲+冒泡,兩種事件流都會觸發DOM的全部對象,從document對象開始,也在document對象結束。DOM標準規定事件流包括三個階段:事件捕獲階段、處於目標階段和事件冒泡階段。
(1) 事件捕獲階段:實際目標(<div>)在捕獲階段不會接收事件。也就是在捕獲階段,事件從document到<html>再到<body>就中止了。
(2) 處於目標階段:事件在<div>上發生並處理。可是事件處理會被當作是冒泡階段的一部分。
(3) 冒泡階段:事件又傳播迴文檔。
來個例子搞一下,以下圖:
圖3.2
上圖點擊btn1的區域,會先彈出「btn1」,緊跟着彈出「content」,這就是一個最典型的冒泡事件。
圖3.3
上圖代碼運行結果爲:先彈出「btn1」,而後彈出「btn2」,最後彈出「content 」。它與前一個代碼的區別是,一個是綁定,一個是註冊。即DOM元素只能綁定一個事件,相似變量,後面的會把前面的覆蓋掉;可是DOM元素能夠註冊多個事件,即在註冊第一個事件的時候,同時註冊了第二個事件,因此在執行的時候,會從第二個(也就是當前元素的最後一個註冊事件)開始執行,直到執行完第三個事件。
四. 閉包
閉包,官方對閉包的解釋是:一個擁有許多變量和綁定了這些變量的環境的表達式(一般是一個函數)。於是,這些變量也是該表達式的一部分。閉包的特色以下:
簡單的說,Javascript容許使用內部函數,即函數定義和函數表達式位於另外一個函數的函數體內。並且,這些內部函數能夠訪問它們所在的外部函數中聲明的全部局部變量、參數和聲明的其餘內部函數。當其中一個這樣的內部函數在包含它們的外部函數以外被調用時,就會造成閉包。
圖4.1
如上圖所示,給函數原型增長一個方法,同時建立一個實例,會獲得結果3.14159。
圖4.2
上圖就是把一個函數return爲一個變量,那麼當建立該函數的實例的時候,全部該變量具備的方法均可以被調用,同時仍是在函數做用域以外被調用,即閉包,結果依舊爲3.14159。
圖4.3
這屬於最容易理解的方式,即直接new一個對象,給它賦予各類屬性和方法,最終結果依舊爲3.14159。
圖4.4
這種方式是使用最多的一種方式,也是最方便的一種方式。(var obj = {}就是聲明一個空的對象。)
閉包的用途以下:
五. call與apply
都「能夠用來代替另外一個對象調用一個方法,將一個函數的對象上下文從初始的上下文改變爲由thisObj指定的新對象」。
apply:apply(thisObj,[argArray])。最多隻能有兩個參數——新this對象和一個數組argArray。若是給該方法傳遞多個參數,則把參數都寫進這個數組裏面,固然,即便只有一個參數,也要寫進數組裏。若是argArray不是一個有效的數組或arguments對象,那麼將致使一個TypeError。若是沒有提供argArray和thisObj任何一個參數,那麼Global對象將被用做thisObj,而且沒法被傳遞任何參數。
call:call(thisObj,Object)。它能夠接受多個參數,第一個參數與apply同樣,後面則是一串參數列表。這個方法主要用在js對象各方法相互調用的時候,使當前this實例指針保持一致,或者在特殊狀況下須要改變this指針。若是沒有提供thisObj參數,那麼 Global 對象被用做thisObj。
圖5.1
如上圖所示,不管是apply仍是call,它的結果都是同樣的,都是調用的前面的函數的方法,可是傳的參數是不同的,固然這只是在參數方面的不一樣。
圖5.2
如上,就是利用call和apply實現繼承,經過給函數賦予屬性和方法,而後給另外一個函數繼承原函數,再建立新函數的實例,就實現了最簡單的繼承。
圖5.3
如上圖所示,即一種多重繼承的實現方式。