【直接收藏】前端JavaScript面試100問(下)
61、常見的 HTTP 請求有哪些 ? 他們的區(qū)別是什么 ?
常見的有5種,分別是GET、HEAD, POST、PUT、 DELETE
GET:它是最常見的方法,用于獲取資源,常用于向服務器查詢某些信息。打開網(wǎng)頁一般都是用GET方法,因為要從 Web 服務器獲取信息
HEAD:類似于 GET請求,只不過返回的響應中沒有具體的內(nèi)容,用于獲取報頭。
POST:向指定資源提交數(shù)據(jù)進行處理請求(例如提交表單或者上傳文件), 數(shù)據(jù)被包含在請求體中。POST請求可能會導致新的資源的建立和/或?qū)σ延匈Y源的修改。
PUT:從客戶端向服務器傳送的數(shù)據(jù)取代指定文檔的內(nèi)容。
DELETE:請求服務器刪除指定的頁面。
最常見的HTTP請求方法是GET 和 POST。GET一般用于獲取/查詢資源信息,而POST一般用于更新資源信息。GET和POST的區(qū)別:
GET提交的數(shù)據(jù)會放在?之后,以問號(?)分割URL 和傳輸數(shù)據(jù),參數(shù)之間以&相連
GET提交的數(shù)據(jù)大小有限制(因為瀏覽器對URL的長度有限制), 而POST 方法提交的數(shù)據(jù)大小沒有限制。
GET方式提交數(shù)據(jù)會帶來安全問題,比如一個登錄頁面通過GET方式提交數(shù)據(jù)時,用戶名和密碼將出現(xiàn)在URL上,如果頁面可以被緩存或者其他人可以訪問這臺機器,就可以從歷史記錄獲得該用戶的賬號和密碼。
62、 JS 的數(shù)據(jù)類型有哪些 ? 如何判斷數(shù)據(jù)類型 ?他們的優(yōu)缺點是什么?
typeof 用來檢測數(shù)據(jù)類型的運算符
檢測的不管是數(shù)組還是正則都返回的是"object",所以typeof不能判斷一個值是否為數(shù)組
instanceof/constructor。檢測某一個實例是否屬于某一個類使用instanceof/constructor可以檢測數(shù)組和正則
用instanceof檢測的時候,只要當前的這個類在實例的原型鏈上(可以通過原型鏈__proto__找到它),檢測出來的結(jié)果都是true。
基本數(shù)據(jù)類型的值是不能用instanceof來檢測的
在類的原型繼承中,instanceof檢測出來的結(jié)果其實是不準確的Object.prototype.toString.call(value) ->找到Object原型上的toString方法,讓方法執(zhí)行,并且讓方法中的this變?yōu)関alue(value->就是我們要檢測數(shù)據(jù)類型的值)。檢測的類型比較多,也比較精準。
63、 symbol 你是怎么理解的 ?
Symbol
是 ES6
新推出的一種基本類型,它表示獨一無二的值
它可以選擇接受一個字符串作為參數(shù)或者不傳,但是相同參數(shù)的兩個Symbol
值不相等
可以通過typeof
判斷是否為Symbol
類型
Symbol.for():用于將描述相同的Symbol
變量指向同一個Symbol
值
Symbol.keyFor():用來檢測該字符串參數(shù)作為名稱的 Symbol
值是否已被登記,返回一個已登記的 Symbol
類型值的key
description:用來返回Symbol
數(shù)據(jù)的描述:
使用場景一:對象添加屬性
使用場景二:給對象添加私有屬性
64、數(shù)組常用方法有那些
數(shù)組的常用方法 這樣的面試題 算是非?;A的面試題 面試官的目的 也不會只是單純的讓你背誦出 數(shù)組的所有方法
這里的關(guān)鍵點 是 常用 這兩個字 面試官的 目的是 通過 這個問題 看你平時在項目中 對于 數(shù)組函數(shù)的應用和理解 然后判斷出 你平時在項目中對于數(shù)組的應用 然后推測出你真實的技術(shù)水平
這里建議的回答方式是 通過一個 自己用的最多的數(shù)組函數(shù)方法 深入展開的說一說 在 實際項目中的應用
例如談到 數(shù)組單元刪除 數(shù)組,splice() 除了要說 函數(shù)的用法之外 還要談到 具體的項目中 刪除數(shù)組單元之后 數(shù)組坍塌的影響 以及如何處理
concat() 連接兩個或更多的數(shù)組,并返回結(jié)果。
join() 把數(shù)組的所有元素放入一個字符串。元素通過指定的分隔符進行分隔。
pop() 刪除并返回數(shù)組的最后一個元素。?
shift() 刪除并返回數(shù)組的第一個元素
push() 向數(shù)組的末尾添加一個或更多元素,并返回新的長度。
unshift() 向數(shù)組的開頭添加一個或更多元素,并返回新的長度。
reverse() 顛倒數(shù)組中元素的順序。
slice() 從某個已有的數(shù)組返回選定的元素
sort() 對數(shù)組的元素進行排序
splice() 刪除元素,并向數(shù)組添加新元素。
toSource() 返回該對象的源代碼。
toString() 把數(shù)組轉(zhuǎn)換為字符串,并返回結(jié)果。
toLocaleString() 把數(shù)組轉(zhuǎn)換為本地數(shù)組,并返回結(jié)果。
valueOf() 返回數(shù)組對象的原始值
65、JavaScript如何存儲cookie
基本語法是 document.cookie = '鍵名=鍵值;expires=時間對象;path=路徑' ;
時效 如果不設定 默認是 seeion 會話時效路徑 如果不設定 默認是 當前文件所在文件夾
設定時效 要 設定一個時間對象 時間對象的時間戳 就是 時效期要注意計算 當前時區(qū) 和 世界標磚時間的時間差
路徑一般設定為根目錄 也就是 '/'
66、柯理化函數(shù)
所謂的柯里化函數(shù) 指的是 把接受多個參數(shù)的函數(shù)變換成接受一個單一參數(shù)的函數(shù) 并且返回接受余下的參數(shù)而且返回結(jié)果的新函數(shù)
優(yōu)點:
1, 參數(shù)復用
例如 一個函數(shù) 有兩個參數(shù) 但是第一個參數(shù)會被反復使用 每次都需要輸入 一個重復的參數(shù)
使用柯里化函數(shù)之后 只需要 輸入一個參數(shù)就可以了
2, 提前確認
提前定義好一個參數(shù) 也就 決定了整個函數(shù)程序的執(zhí)行方向 避免每次都執(zhí)行判斷比較等
缺點:
只能提前定義一個參數(shù) 如果想要提前定義多個參數(shù) 這樣的語法是不支持
柯里化函數(shù)執(zhí)行效能上的問題:
存取arguments對象通常要比存取命名參數(shù)要慢一點
一些老版本的瀏覽器在arguments.length的實現(xiàn)上是相當慢的
使用 函數(shù).apply() 和 函數(shù).call() 通常比直接調(diào)用 fn() 稍微慢點
創(chuàng)建大量嵌套作用域和閉包函數(shù)會帶來花銷,無論是在內(nèi)存還是速度上
67、對象遍歷方法
JavaScript中 對象的遍歷方法
for...in
基本語法是?for( 變量?in?對象 ){ 循環(huán)體程序 }
這里要注意的是
1, 變量中存儲的鍵名 通過鍵名獲取對象中存儲的鍵值
? 因為是變量 點語法取值 不支持解析變量 要使用 對象[鍵名] 獲取鍵值
2, 循環(huán)變量 定義 let 和 var 定義 執(zhí)行效果是不同的
Object.keys( 對象 )
返回一個數(shù)組 是 當前對象 所有鍵名組成的數(shù)組
之后再循環(huán)遍歷這個數(shù)組 再執(zhí)行操作
Object.value( 對象 )
返回一個數(shù)組 是 當前對象 所有鍵值組成的數(shù)組
之后再循環(huán)遍歷這個數(shù)組 再執(zhí)行操作
68、數(shù)組扁平化
數(shù)組扁平化
所謂的數(shù)組扁平化就是將多維數(shù)組轉(zhuǎn)化為一維數(shù)組一般數(shù)組扁平化,數(shù)組中存儲的多維數(shù)據(jù)都是數(shù)組 不會是對象或者函數(shù)
最常用的方法 就是 數(shù)組.toString() 將數(shù)組轉(zhuǎn)化為字符串 結(jié)果是 獲取數(shù)組中的每一個單元的數(shù)據(jù) 組成一個字符串 使用逗號間隔 再 以逗號為間隔 將字符串 轉(zhuǎn)化為數(shù)組
還可以使用 數(shù)組.some() 方法 判斷數(shù)組中是不是還存在數(shù)組 在使用 展開運算符 賦值
另外 ES6 語法中 新增的 flat函數(shù)也可以實現(xiàn)數(shù)組的扁平化參數(shù)是固定的
69、typeof 原理
利用 typeof 是根據(jù)返回值的結(jié)果來判斷數(shù)據(jù)類型
具體返回值 一共是 number, string, object, boolean, function, undefined
其中 數(shù)組 null 對象 的返回值 都是 object這樣的話具體的數(shù)據(jù)類型就不能區(qū)分的非常明確 在實際項目中 就不能準確的區(qū)分
如果想要具體的 區(qū)分 數(shù)據(jù)類型 需要使用 Object.prototype.toString.call() 方法 返回值是
object String?字符串
object Number?數(shù)值類型
object Boolean?布爾類型
object Undefined?undefined類型
object Null?null類型
object Function?函數(shù)類型
object Array?數(shù)組類型
70、介紹類型轉(zhuǎn)化
JavaScript 因為是 弱類型計算機語言 存儲數(shù)據(jù)時 對變量儲存的數(shù)據(jù)類型沒有設定因此一個變量中可以存儲任意類型的數(shù)據(jù) 在程序的執(zhí)行過程中 就會遇到需要數(shù)據(jù)類型轉(zhuǎn)化的情況
自動轉(zhuǎn)化
自動轉(zhuǎn)化為字符串
數(shù)據(jù) 直接轉(zhuǎn)化為 對應的字符串
? ? ?? ?自動轉(zhuǎn)化為數(shù)值類型 ? ?轉(zhuǎn)化為 對應的數(shù)值 ?? ? ?1 ? ? ?true ? ? ?0 ? ? ?false ?null "" ?'' ? ?
符合數(shù)字規(guī)范的字符串
轉(zhuǎn)化為 NaN
? ? ? ? 不符合數(shù)字規(guī)范的字符串
? ? ? ? ? undefined
自動轉(zhuǎn)化為數(shù)值類型
? ? ? ? ? false:
? ? ? ? ? ? ? 0 0.0000 '' ? NaN ? null ? ? undefined
? ? ? ? ? true:
? ? ? ? ? ? ? 其他情況都轉(zhuǎn)化為 true
強制轉(zhuǎn)化
強制轉(zhuǎn)化為布爾類型
Boolean( 變量 / 表達式 )
? ? ? ? ? ? ? 轉(zhuǎn)化原則 和 自動轉(zhuǎn)化原則完全相同
? ? ? ? ? ? ? false : 0 ? 0.000 ? '' ? null ? NaN undefined
? ? ? ? ? ? ? true : 其他情況都轉(zhuǎn)化為true
? 強制轉(zhuǎn)化為字符串類型
? ? ? String( 變量 / 表達式 );
? ? ? ? ? 轉(zhuǎn)化原則 和 自動轉(zhuǎn)化原則完全相同
? ? ? ? ? 不會改變 變量中存儲的原始數(shù)據(jù)
? ? 變量.toString( 進制 ) ;
? ? ? ? ? 轉(zhuǎn)化原則 和 自動轉(zhuǎn)化原則完全相同
? ? ? ? ? 不會改變 變量中存儲的原始數(shù)據(jù)
? ? ? ? ? 如果是 整數(shù)類型 可以 設定 轉(zhuǎn)化的進制
? ? ? ? ? 變量 存儲 null 或者 undefined不支持
? 強制轉(zhuǎn)化為數(shù)值類型
? ? ? Number()
? ? ? ? ? 轉(zhuǎn)化原則 和 自動轉(zhuǎn)化完全相同
? ? ? ? ? 不會改變 變量中存儲的原始內(nèi)容
? ? ? parseInt()
? ? ? ? ? 從 左側(cè)起 獲取符合整數(shù)語法規(guī)范的內(nèi)容部分
? ? ? ? ? 如果 左起第一個字符就不符合整數(shù)語法規(guī)范
? ? ? ? ? 執(zhí)行結(jié)果是 NaN
? ? ? parseFloat()
? ? ? ? ? 從 左側(cè)起 獲取符合浮點數(shù)語法規(guī)范的內(nèi)容部分
? ? ? ? ? 如果 左起第一個字符就不符合浮點數(shù)語法規(guī)范
? ? ? ? ? 執(zhí)行結(jié)果是 NaN ? ?
71、執(zhí)行上下文
執(zhí)行上下文:指當前執(zhí)行環(huán)境中的變量、函數(shù)聲明,參數(shù)(arguments),作用域鏈,this等信息。分為全局執(zhí)行上下文、函數(shù)執(zhí)行上下文,其區(qū)別在于全局執(zhí)行上下文只有一個,函數(shù)執(zhí)行上下文在每次調(diào)用函數(shù)時候會創(chuàng)建一個新的函數(shù)執(zhí)行上下文。
變量對象是與執(zhí)行上下文相關(guān)的數(shù)據(jù)作用域,存儲了上下文中定義的變量和函數(shù)聲明。
變量對象式一個抽象的概念,在不同的上下文中,表示不同的對象:
全局執(zhí)行上下文的變量對象全局執(zhí)行上下文中,變量對象就是全局對象。在頂層js代碼中,this指向全局對象,全局變量會作為該對象的屬性來被查詢。在瀏覽器中,window就是全局對象。函數(shù)執(zhí)行上下文的變量對象函數(shù)上下文中,變量對象VO就是活動對象AO。初始化時,帶有arguments屬性。函數(shù)代碼分成兩個階段執(zhí)行進入執(zhí)行上下文時,此時變量對象包括形參函數(shù)聲明,會替換已有變量對象變量聲明,不會替換形參和函數(shù)函數(shù)執(zhí)行
執(zhí)行上下文棧的作用是用來跟蹤代碼的,由于JS是單線程的,每次只能做一件事情,其他的事情會放在指定的上下文棧中排隊等待執(zhí)行。
JS解釋器在初始化代碼的時候,首先會創(chuàng)建一個新的全局執(zhí)行上下文到執(zhí)行上下文棧頂中,然后隨著每次函數(shù)的調(diào)用都會創(chuàng)建一個新的執(zhí)行上下文放入到棧頂中,隨著函數(shù)執(zhí)行完畢后被執(zhí)行上下文棧頂彈出,直到回到全局的執(zhí)行上下文中。
首先創(chuàng)建了全局執(zhí)行上下文,當前全局執(zhí)行上下文處于活躍狀態(tài)。全局代碼中有2個函數(shù) getName 和 getYear,然后調(diào)用 getName 函數(shù),JS引擎停止執(zhí)行全局執(zhí)行上下文,創(chuàng)建了新的函數(shù)執(zhí)行上下文,且把該函數(shù)上下文放入執(zhí)行上下文棧頂。getName 函數(shù)里又調(diào)用了 getYear 函數(shù),此時暫停了 getName 的執(zhí)行上下文,創(chuàng)建了 getYear 函數(shù)的新執(zhí)行上下文,且把該函數(shù)執(zhí)行上下文放入執(zhí)行上下文棧頂。當 getYear 函數(shù)執(zhí)行完后,其執(zhí)行上下文從棧頂出棧,回到了 getName 執(zhí)行上下文中繼續(xù)執(zhí)行。當 getName 執(zhí)行完后,其執(zhí)行上下文從棧頂出棧,回到了全局執(zhí)行上下文中。
72、閉包的問題和優(yōu)化
閉包:是指有權(quán)訪問另外一個函數(shù)作用域中的變量的函數(shù)。創(chuàng)建閉包的常見方式就是在一個函數(shù)內(nèi)部創(chuàng)建另外一個函數(shù)。
作用:
1、可以讀取函數(shù)內(nèi)部的變量2、相當于劃出了一塊私有作用域,避免數(shù)據(jù)污染;3、讓變量始終保存在內(nèi)存中
閉包有三個特性:
1.函數(shù)嵌套函數(shù)
2.函數(shù)內(nèi)部可以引用外部的參數(shù)和變量
3.參數(shù)和變量不會被垃圾回收機制回收
閉包的問題
閉包會產(chǎn)生不銷毀的上下文,會導致棧/堆內(nèi)存消耗過大,有時候也會導致內(nèi)存泄漏等,影響頁面的運行性能,所以在真實項目中,要合理應用閉包!
閉包的優(yōu)化
? 原始代碼
優(yōu)化代碼
73、瀏覽器和Node事件循環(huán)的區(qū)別
一、全局環(huán)境下this的指向
在node中this指向global而在瀏覽器中this指向window,這就是為什么underscore中一上來就定義了一 root;
而且在瀏覽器中的window下封裝了不少的API 比如 alert 、document、location、history 等等還有很多。我門就不能在node環(huán)境中xxx();或window.xxx();了。因為這些API是瀏覽器級別的封裝,存javascript中是沒有的。當然node中也提供了不少node特有的API。
二、js引擎
在瀏覽器中不同的瀏覽器廠商提供了不同的瀏覽器內(nèi)核,瀏覽器依賴這些內(nèi)核解釋折我們編寫的js。但是考慮到不同內(nèi)核的少量差異,我們需要對應兼容性好在有一些優(yōu)秀的庫幫助我們處理這個問題比如jquery、underscore等等。
nodejs是基于Chromes JavaScript runtime,也就是說,實際上它是對GoogleV8引擎(應用于Google Chrome瀏覽器)進行了封裝。V8引 擎執(zhí)行Javascript的速度非???,性能非常好。
NodeJS并不是提供簡單的封裝,然后提供API調(diào)用,如果是這樣的話那么它就不會有現(xiàn)在這么火了。Node對一些特殊用例進行了優(yōu)化,提供了替代的API,使得V8在非瀏覽器環(huán)境下運行得更好。例如,在服務器環(huán)境中,處理二進制數(shù)據(jù)通常是必不可少的,但Javascript對此支持不足,因此,V8.Node增加了Buffer類,方便并且高效地 處理二進制數(shù)據(jù)。因此,Node不僅僅簡單的使用了V8,還對其進行了優(yōu)化,使其在各環(huán)境下更加給力。
三、DOM操作
瀏覽器中的js大多數(shù)情況下是在直接或間接(一些虛擬DOM的庫和框架)的操作DOM。因為瀏覽器中的代碼主要是在表現(xiàn)層工作。但是node是一門服務端技術(shù)。沒有一個前臺頁面,所以我門不會再node中操作DOM。
四、I/O讀寫
與瀏覽器不同,我們需要像其他服務端技術(shù)一樣讀寫文件,nodejs提供了比較方便的組件。而瀏覽器(確保兼容性的)想在頁面中直接打開一個本地的圖片就麻煩了好多(別和我說這還不簡單,相對路徑。。。。。。試試就知道了要么找個庫要么二進制流,要么上傳上去有了網(wǎng)絡地址在顯示。不然人家為什么要搞一個js庫呢),而這一切node都用一個組件搞定了。
五、模塊加載
javascript有個特點,就是原生沒提供包引用的API一次性把要加載的東西全執(zhí)行一遍,這里就要看各位閉包的功力了。所用東西都在一起,沒有分而治之,搞的特別沒有邏輯性和復用性。如果頁面簡單或網(wǎng)站當然我們可以通過一些AMD、CMD的js庫(比如requireJS 和 seaJS)搞定事實上很多大型網(wǎng)站都是這么干的。
在nodeJS中提供了CMD的模塊加載的API,如果你用過seaJS,那么應該上手很快。
node還提供了npm 這種包管理工具,能更有效方便的管理我們飲用的庫
74、移動端點擊延遲
原因 :
為了確定用戶是要做單擊 還是雙擊 還是要做其他的操作 因此移動端 當你點擊時 會有?300毫秒延遲 為了等待判斷用戶的下一步操作是什么
解決方案1
解決方案2 更改默認的視口寬度
解決方案3 CSS touch-action
75、cookie屬性
cookie的常見屬性
鍵名?cookie鍵值對的鍵名
鍵值?cookie鍵值對的鍵值
expirescookie的時效 分為 session會話時效 時間時效 時間時效是服務器時間也就是世界標準時間
path路徑 符合路徑的文件才能訪問cookie
httponly設置 為?true?了之后可以防止js程序訪問 防止 xss攻擊 增加cookie的安全性
secure設置 為?true?了之后cookie只能通過https協(xié)議發(fā)送 http協(xié)議是不能發(fā)送的 這樣也是為了增加cookie的安全性
76、反柯里化
反柯里化的作用是,當我們調(diào)用某個方法,不用考慮這個對象在被設計時,是否擁有這個方法,只要這個方法適用于它,我們就可以對這個對象使用它
例如
我們先來看看上面這段代碼有什么作用。
我們要把Array.prototype.push方法轉(zhuǎn)換成一個通用的push函數(shù),只需要這樣做:
arguments本來是沒有push方法的,通常,我們都需要用Array.prototype.push.call來實現(xiàn)push方法,但現(xiàn)在,直接調(diào)用push函數(shù),既簡潔又意圖明了。
我們不用考慮對象是否擁有這個方法,只要它適用于這個方法,那就可以使用這個方法(類似于鴨子類型)。
我們來分析一下調(diào)用Array.prototype.push.uncurring()這句代碼時,發(fā)生了什么事情:
//測試一下
看到這里你應該對柯里化和反柯里化有了一個初步的認識了,但要熟練的運用在開發(fā)中,還需要我們更深入的去了解它們內(nèi)在的含義。
77、千分位
這里的需求 本質(zhì)上是要 將 數(shù)字 轉(zhuǎn)化為 帶有千分位字符串 方法有很多
方法1 正則表達式
方法2 字符串替換
方法3 數(shù)字轉(zhuǎn)數(shù)組 反轉(zhuǎn)后 添加 , 再反轉(zhuǎn)回來拼接為字符串
方法4 利用while循環(huán)拼接字符串每隔3個數(shù)字加一個分隔符,首尾不加
方法5 利用while循環(huán)在數(shù)組里push分隔符,首尾不加
78、load和ready區(qū)別
document.ready:
是ready,表示文檔結(jié)構(gòu)已經(jīng)加載完成 不包含圖片等非文字媒體文件 只要html標簽結(jié)構(gòu)加載完畢就可以;
document.load:
是onload,指示頁面包含圖片等文件在內(nèi)的所有元素都加載完成。
1、概念
2、作用
document.ready:
在DOM加載完成后就可以可以對DOM進行操作。
一般情況一個頁面響應加載的順序是,域名解析-加載html-加載js和css-加載圖片等其他信息。
那么Dom Ready應該在“加載js和css”和“加載圖片等其他信息”之間,就可以操作Dom了。
document.load:
在document文檔加載完成后就可以可以對DOM進行操作,document文檔包括了加載圖片等其他信息。
那么Dom Load就是在頁面響應加載的順序中的“加載圖片等其他信息”之后,就可以操作Dom了。
3、加載順序
document.ready:
文檔加載的順序:域名解析-->加載HTML-->加載JavaScript和CSS-->加載圖片等非文字媒體文件。
只要<img>標簽加載完成,不用等該圖片加載完成,就可以設置圖片的屬性或樣式等。
在原生JavaScript中沒有Dom ready的直接方法。
document.load:
文檔加載的順序:域名解析-->加載HTML-->加載JavaScript和CSS-->加載圖片等非文字媒體文件。
DOM load在加載圖片等非文字媒體文件之后,表示在document文檔加載完成后才可以對DOM進行操作,document文檔包括了加載圖片等非文字媒體文件。
例如,需要等該圖片加載完成,才可以設置圖片的屬性或樣式等。
在原生JavaScript中使用onload事件。
79、自定義事件
自定義事件,就是自己定義事件類型,自己定義事件處理函數(shù)。
我們平時操作dom時經(jīng)常會用到onclick、onmousemove等瀏覽器特定行為的事件類型。
封裝is自定義事件基本的構(gòu)思:
在js默認事件中事件類型以及對應的執(zhí)行函數(shù)是一一對應的,但是自定義事件,需要一個映射表來建立兩者之間的聯(lián)系。
如:?這樣每個類型可以處理多個事件函數(shù)
代碼實現(xiàn):
為什么要把方法添加到對象原型上?
在構(gòu)造函數(shù)中加屬性,在原型中加方法。
將屬性和方法都寫在構(gòu)造函數(shù)里是沒有問題的,但是每次進行實例化的過程中,要重復創(chuàng)建功能不變的方法。
由于方法本質(zhì)上是函數(shù),其實也就是在堆內(nèi)存中又新建了一個對象空間存放存儲函數(shù),造成了不必要的資源浪費。
在本身添加會導致每次對象實例化時代碼被復制,都需要申請一塊內(nèi)存存放該方法。
寫一個EventEmitter類,包括on()、off()、once()、emit()方法once():為指定事件注冊一個單次監(jiān)聽器,單次監(jiān)聽器最多只觸發(fā)一次,觸發(fā)后立即解除監(jiān)聽器。
80、setTimeout實現(xiàn)setInterval
setTimeout() :在指定的毫秒數(shù)后調(diào)用函數(shù)或計算表達式,只執(zhí)行一次。
setInterval() :按照指定的周期(以毫秒計)來調(diào)用函數(shù)或計算表達式。方法會不停地調(diào)用函數(shù),直到 clearInterval() 被調(diào)用或窗口被關(guān)閉。
思路是使用遞歸函數(shù),不斷地去執(zhí)行setTimeout從而達到setInterval的效果,看代碼
這個mySetInterval函數(shù)有一個叫做interval的內(nèi)部函數(shù),它通過setTimeout來自動被調(diào)用,在interval中有一個閉包,調(diào)用了回調(diào)函數(shù)并通過setTimeout再次調(diào)用了interval。
一個更好的實現(xiàn)我們再增加一個額外的參數(shù)用來標明代碼執(zhí)行的次數(shù)
81、避免回調(diào)地獄
使用 async await 配合 promise 是 解決回調(diào)地獄的終極方法
async/await特點
async function語法
await語法
函數(shù)形式
82、callee和caller的作用
caller返回一個函數(shù)的引用,這個函數(shù)調(diào)用了當前的函數(shù);callee放回正在執(zhí)行的函數(shù)本身的引用,它是arguments的一個屬性
callercaller返回一個函數(shù)的引用,這個函數(shù)調(diào)用了當前的函數(shù)。使用這個屬性要注意:1 這個屬性只有當函數(shù)在執(zhí)行時才有用2 如果在javascript程序中,函數(shù)是由頂層調(diào)用的,則返回null
上面的代碼中,b調(diào)用了a,那么a.caller返回的是b的引用,結(jié)果如下:
如果直接調(diào)用a(即a在任何函數(shù)中被調(diào)用,也就是頂層調(diào)用),返回null:
callee
callee放回正在執(zhí)行的函數(shù)本身的引用,它是arguments的一個屬性
使用callee時要注意:calleecallee放回正在執(zhí)行的函數(shù)本身的引用,它是arguments的一個屬性使用callee時要注意:
83、統(tǒng)計字符串中字母個數(shù)或統(tǒng)計最多的字母數(shù)
統(tǒng)計字母出現(xiàn)的次數(shù)
統(tǒng)計字符出現(xiàn)次數(shù)最多的字母
84、面對對象和面向過程的區(qū)別
85、eval
86、proxy
一、proxy
proxy在目標對象的外層搭建了一層攔截,外界對目標對象的某些操作,必須通過這層攔截
proxy對象是obj對象的原型,obj對象本身并沒有time屬性,所以根據(jù)原型鏈,會在proxy對象上讀取該屬性,導致被攔截
Proxy的作用
對于代理模式 Proxy 的作用主要體現(xiàn)在三個方面
攔截和監(jiān)視外部對對象的訪問降低函數(shù)或類的復雜度在復雜操作前對操作進行校驗或?qū)λ栀Y源進行管理
二、Proxy所能代理的范圍--handler
三、Proxy場景
3.1 實現(xiàn)私有變量
3.2 抽離校驗模塊
3.3 訪問日志
3.4 預警和攔截
3.5 過濾操作