javascript
个人JS体系整理(二)
一.?eval
eval()函數(shù)計(jì)算JavaScript字符串,并把它作為腳本代碼來執(zhí)行。如果參數(shù)是一個表達(dá)式,eval()函數(shù)將執(zhí)行表達(dá)式。如果參數(shù)是Javascript語句,eval()將執(zhí)行Javascript語句。
圖1.1
如上圖所示,第一個eval內(nèi)部為一個函數(shù)表達(dá)式,在執(zhí)行該函數(shù)的同時,定義了兩個全局變量X和Y,所以結(jié)果分別為200、4、27。
由于因?yàn)樗鼤?zhí)行任意傳給它的代碼,在代碼字符串未知或者是來自一個不信任的源時,會導(dǎo)致安全問題,同時非常耗性能(它會執(zhí)行兩次2次,一次解析成js語句,一次執(zhí)行),最重要的是,99.9%使用eval 的場景都有不使用eval的解決方案,所以在任何情況下我們都應(yīng)該避免使用eval函數(shù)。
二.?null與undefined 的區(qū)別
(1)?null表示一個對象是“沒有值”的值,也就是值為“空”;undefined表示一個變量聲明了沒有初始化(即沒有賦值)。
(2)?undefined不是一個有效的JSON,而null是;undefined的類型(typeof)是undefined,而null的類型(typeof)是object。
(3)?在驗(yàn)證null時,一定要使用“===” ,因?yàn)椤?/span>==”無法分別null和undefined!
圖2.1
三.?事件與事件流
(1)?事件
事件是文檔或者瀏覽器窗口中發(fā)生的,特定的交互瞬間,也可以理解為是用戶或?yàn)g覽器自身執(zhí)行的某種動作,如click,change和hover都是事件的名字,同時事件是javaScript和DOM之間交互的橋梁。
(2)?事件流
事件發(fā)生時會在元素節(jié)點(diǎn)與根節(jié)點(diǎn)之間按照特定的順序傳播,路徑所經(jīng)過的所有節(jié)點(diǎn)都會收到該事件,這個傳播過程即DOM事件流。事件流有兩種模型,即捕獲型事件流和冒泡型事件流。
冒泡型事件流:事件的傳播是從最特定的事件目標(biāo)到最不特定的事件目標(biāo)。即從DOM樹的葉子到根。
捕獲型事件流:事件的傳播是從最不特定的事件目標(biāo)到最特定的事件目標(biāo)。即從DOM樹的根到葉子。
圖3.1
如上圖所示,DOM標(biāo)準(zhǔn)采用捕獲+冒泡,兩種事件流都會觸發(fā)DOM的所有對象,從document對象開始,也在document對象結(jié)束。DOM標(biāo)準(zhǔn)規(guī)定事件流包括三個階段:事件捕獲階段、處于目標(biāo)階段和事件冒泡階段。
(1)?事件捕獲階段:實(shí)際目標(biāo)(<div>)在捕獲階段不會接收事件。也就是在捕獲階段,事件從document到<html>再到<body>就停止了。
(2)?處于目標(biāo)階段:事件在<div>上發(fā)生并處理。但是事件處理會被看成是冒泡階段的一部分。
(3)?冒泡階段:事件又傳播回文檔。
來個例子搞一下,如下圖:
圖3.2
上圖點(diǎn)擊btn1的區(qū)域,會先彈出“btn1”,緊跟著彈出“content”,這就是一個最典型的冒泡事件。
圖3.3
上圖代碼運(yùn)行結(jié)果為:先彈出“btn1”,然后彈出“btn2”,最后彈出“content ”。它與前一個代碼的區(qū)別是,一個是綁定,一個是注冊。即DOM元素只能綁定一個事件,類似變量,后面的會把前面的覆蓋掉;但是DOM元素可以注冊多個事件,即在注冊第一個事件的時候,同時注冊了第二個事件,所以在執(zhí)行的時候,會從第二個(也就是當(dāng)前元素的最后一個注冊事件)開始執(zhí)行,直到執(zhí)行完第三個事件。
四.?閉包
閉包,官方對閉包的解釋是:一個擁有許多變量和綁定了這些變量的環(huán)境的表達(dá)式(通常是一個函數(shù))。因而,這些變量也是該表達(dá)式的一部分。閉包的特點(diǎn)如下:
簡單的說,Javascript允許使用內(nèi)部函數(shù),即函數(shù)定義和函數(shù)表達(dá)式位于另一個函數(shù)的函數(shù)體內(nèi)。而且,這些內(nèi)部函數(shù)可以訪問它們所在的外部函數(shù)中聲明的所有局部變量、參數(shù)和聲明的其他內(nèi)部函數(shù)。當(dāng)其中一個這樣的內(nèi)部函數(shù)在包含它們的外部函數(shù)之外被調(diào)用時,就會形成閉包。
圖4.1
如上圖所示,給函數(shù)原型增加一個方法,同時創(chuàng)建一個實(shí)例,會得到結(jié)果3.14159。
??圖4.2
上圖就是把一個函數(shù)return為一個變量,那么當(dāng)創(chuàng)建該函數(shù)的實(shí)例的時候,所有該變量具有的方法都可以被調(diào)用,同時還是在函數(shù)作用域之外被調(diào)用,即閉包,結(jié)果依舊為3.14159。
圖4.3
這屬于最容易理解的方式,即直接new一個對象,給它賦予各種屬性和方法,最終結(jié)果依舊為3.14159。
圖4.4
這種方式是使用最多的一種方式,也是最方便的一種方式。(var obj = {}就是聲明一個空的對象。)
閉包的用途如下:
五.?call與apply
都“可以用來代替另一個對象調(diào)用一個方法,將一個函數(shù)的對象上下文從初始的上下文改變?yōu)橛?/span>thisObj指定的新對象”。
apply:apply(thisObj,[argArray])。最多只能有兩個參數(shù)——新this對象和一個數(shù)組argArray。如果給該方法傳遞多個參數(shù),則把參數(shù)都寫進(jìn)這個數(shù)組里面,當(dāng)然,即使只有一個參數(shù),也要寫進(jìn)數(shù)組里。如果argArray不是一個有效的數(shù)組或arguments對象,那么將導(dǎo)致一個TypeError。如果沒有提供argArray和thisObj任何一個參數(shù),那么Global對象將被用作thisObj,并且無法被傳遞任何參數(shù)。
call:call(thisObj,Object)。它可以接受多個參數(shù),第一個參數(shù)與apply一樣,后面則是一串參數(shù)列表。這個方法主要用在js對象各方法相互調(diào)用的時候,使當(dāng)前this實(shí)例指針保持一致,或者在特殊情況下需要改變this指針。如果沒有提供thisObj參數(shù),那么 Global 對象被用作thisObj。
圖5.1
如上圖所示,無論是apply還是call,它的結(jié)果都是一樣的,都是調(diào)用的前面的函數(shù)的方法,但是傳的參數(shù)是不一樣的,當(dāng)然這只是在參數(shù)方面的不同。
圖5.2
如上,就是利用call和apply實(shí)現(xiàn)繼承,通過給函數(shù)賦予屬性和方法,然后給另一個函數(shù)繼承原函數(shù),再創(chuàng)建新函數(shù)的實(shí)例,就實(shí)現(xiàn)了最簡單的繼承。
圖5.3
如上圖所示,即一種多重繼承的實(shí)現(xiàn)方式。
?
轉(zhuǎn)載于:https://www.cnblogs.com/andyzjy/p/10477879.html
總結(jié)
以上是生活随笔為你收集整理的个人JS体系整理(二)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 10个人有9个答错,另外1个只对一半:数
- 下一篇: 我都服了,为啥上游接口返回的汉字总是乱码