javascript
个人JS体系整理(二)
一.?eval
eval()函數計算JavaScript字符串,并把它作為腳本代碼來執行。如果參數是一個表達式,eval()函數將執行表達式。如果參數是Javascript語句,eval()將執行Javascript語句。
圖1.1
如上圖所示,第一個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!
圖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
如上圖所示,即一種多重繼承的實現方式。
?
轉載于:https://www.cnblogs.com/andyzjy/p/10477879.html
總結
以上是生活随笔為你收集整理的个人JS体系整理(二)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 10个人有9个答错,另外1个只对一半:数
- 下一篇: 我都服了,为啥上游接口返回的汉字总是乱码