javascript
可为空的对象必须具有一个值_前端:这里有8个常见的JavaScript经典问题,总有一个你不会的...
參考前端小智:https://juejin.im/post/5d2d146bf265da1b9163c5c9
1.了解函數(shù)提升
使用var關(guān)鍵字聲明的變量在JavaScript中會被提升,并在內(nèi)存中分配值undefined。 但初始化恰發(fā)生在你給變量賦值的地方。 另外,var聲明的變量是函數(shù)作用域的,而let和const是塊作用域的。
2.什么是暫時死區(qū)TDZ?
let和const聲明可以讓變量在其作用域上受限于它所使用的塊、語句或表達式。與var不同的是,這些變量沒有被提升,并且有一個所謂的暫時死區(qū)(TDZ)。試圖訪問TDZ中的這些變量將引發(fā)ReferenceError,因為只有在執(zhí)行到達聲明時才能訪問它們。
下表概述了與JavaScript中使用的不同關(guān)鍵字聲明的變量對應(yīng)的提升行為和使用域:
四個選項:關(guān)鍵字,提升,作用域,創(chuàng)建全局屬性。
3.如何保存 i 的指向?
在for循環(huán)的頭部聲明帶有var關(guān)鍵字的變量會為該變量創(chuàng)建單個綁定(存儲空間)。
如果使用 let 聲明一個具有塊級作用域的變量,則為每個循環(huán)迭代創(chuàng)建一個新的綁定。
解決這個問題的另一種方法是使用閉包。
4.是否存在堆棧溢出?
JavaScript并發(fā)模型基于“事件循環(huán)”。 瀏覽器是執(zhí)行JS代碼提供運行時環(huán)境之一。
瀏覽器的主要組件包括調(diào)用堆棧,事件循環(huán)**,任務(wù)隊列和Web API**。 像setTimeout,setInterval和Promise這樣的全局函數(shù)不是JavaScript的一部分,而是 Web API 的一部分。 JavaScript 環(huán)境的可視化形式如下所示:
JS調(diào)用棧是后進先出(LIFO)的。引擎每次從堆棧stack中取出一個函數(shù),然后從上到下依次運行代碼。每當(dāng)它遇到一些異步代碼,如setTimeout,就把它交給Web API(箭頭1)。因此,每當(dāng) 事件 被觸發(fā)時,callback 都會被發(fā)送到任務(wù)隊列(箭頭2)。
事件循環(huán)(Event loop)不斷地監(jiān)視任務(wù)隊列(Task Queue),并按它們排隊的順序一次處理一個回調(diào)。每當(dāng)調(diào)用 堆棧(call stack) 為空時,Event loop獲取回調(diào)并將其放入堆棧(stack )(箭頭3)中進行處理。請記住,如果調(diào)用堆棧不是空的,則事件循環(huán)不會將任何回調(diào)推入堆棧。
現(xiàn)在,有了這些知識,讓我們來回答前面提到的問題:
步驟:
5.執(zhí)行foo函數(shù),頁面是否卡死(卡頓)?
必須會卡死!
大多數(shù)時候,開發(fā)人員假設(shè)在事件循環(huán)圖中只有一個任務(wù)隊列。但事實并非如此,我們可以有多個任務(wù)隊列。由瀏覽器選擇其中的一個隊列并在該隊列中處理回調(diào)。
在底層來看,JavaScript中有宏任務(wù)和微任務(wù)。setTimeout回調(diào)是宏任務(wù),而Promise回調(diào)是微任務(wù)。
主要的區(qū)別在于他們的執(zhí)行方式。宏任務(wù)在單個循環(huán)周期中一次一個地推入堆棧,但是微任務(wù)隊列總是在執(zhí)行后返回到事件循環(huán)之前清空。因此,如果你以處理條目的速度向這個隊列添加條目,那么你就永遠在處理微任務(wù)。只有當(dāng)微任務(wù)隊列為空時,事件循環(huán)才會重新渲染頁面。每次調(diào)用'foo'都會繼續(xù)在微任務(wù)隊列上添加另一個'foo'回調(diào),因此事件循環(huán)無法繼續(xù)處理其他事件(滾動,單擊等),直到該隊列完全清空為止。 因此,它會阻止渲染。
6.如何使 obj 展開運算而不導(dǎo)致類型錯誤?
var obj = { x: 1, y: 2, z: 3 };[...obj]; // TypeError展開語法 和 for-of 語句遍歷 iterable對象 定義要遍歷的數(shù)據(jù)。Array 或 Map 是具有默認迭代行為的內(nèi)置迭代器。對象不是可迭代的,但是可以通過使用iterable和iterator協(xié)議使它們可迭代。
在Mozilla文檔中,如果一個對象實現(xiàn)了@@iterator方法,那么它就是可迭代的,這意味著這個對象(或者它原型鏈上的一個對象)必須有一個帶有@@iterator鍵的屬性,這個鍵可以通過常量Symbol.iterator獲得。
上述語句可能看起來有點冗長,但是下面的示例將更有意義:
還可以使用 generator 函數(shù)來定制對象的迭代行為:
7.打印的結(jié)果是什么
知識點:
for-in循環(huán)遍歷對象本身的可枚舉屬性以及對象從其原型繼承的屬性。 可枚舉屬性是可以在for-in循環(huán)期間包含和訪問的屬性。
現(xiàn)在你已經(jīng)掌握了這些知識,應(yīng)該很容易理解為什么我們的代碼要打印這些特定的屬性:
8.this 始終指向調(diào)用方法的對象
在全局范圍內(nèi)初始化x時,它成為window對象的屬性(不是嚴格的模式)。看看下面的代碼:
可以斷言:
window.x === 10; // truethis 始終指向調(diào)用方法的對象。因此,在foo.getx()的例子中,它指向foo對象,返回90的值。而在xGetter()的情況下,this指向 window對象, 返回 window 中的x的值,即10。
要獲取 foo.x的值,可以通過使用 Function.prototype.bind 將this的值綁定到foo對象來創(chuàng)建新函數(shù)。
let getFooX = foo.getX.bind(foo);getFooX(); // 90總結(jié)
以上是生活随笔為你收集整理的可为空的对象必须具有一个值_前端:这里有8个常见的JavaScript经典问题,总有一个你不会的...的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: ps设置渐变色(PS设置渐变色背景)
- 下一篇: sql 账号查询一个表勾选那个权限_Sp