中級前端面試題必備知識點(2.5w+月薪)進階

中級前端面試題必備知識點(2.5w+月薪)進階

&時光

於 2021-05-09 19:27:38 發佈

510
收藏 11
分類專欄: vue react javascript 文章標籤: html vue.js reactjs javascript css
版權

vue
同時被 3 個專欄收錄
30 篇文章0 訂閱
訂閱專欄

react
20 篇文章0 訂閱
訂閱專欄

javascript
38 篇文章0 訂閱
訂閱專欄
中級前端面試題必備知識點(2.5w+月薪)進階
前端已經不再是5年前剛開始火爆時候的那種html+css+js+jquery的趨勢了,現在需要你完全瞭解前端開發的同時,還要具備將上線、持續化、閉環、自動化、語義化、封裝......等概念熟練運用到工作中的一個職業,甚至用人部門還希望你瞭解並掌握深度學習及機器學習的相關概念。在面試過程中,各部門交叉面試的時候會提問一些關於後端的知識。

假如你想要拿到2.5w+月薪,你的能力應該達到掌握以下全部知識點並有過開發後端接口與數據處理(node、java、c......必須掌握一種)的經驗。本文就是結合自己的工作、面試經驗,同時爲那些想要衝擊2w+薪資的1-3年新手們準備的。

需要注意的是,所有大廠的社招會按照你當前工作經驗進行+1,+2的難度提升(假設你工作一年,會按照三年工作經驗進行招聘,同時二三面會按照你的項目經驗進行擇優篩選)所以起步是互聯網公司的同學佔了很大的優勢,有些小夥伴在國企工作一年~三年,項目經驗的欠缺導致競爭力不足,沒別的辦法,建議早日跳出自己的舒適圈,之後你會體會到不一樣的前端開發。以下是面試時高頻出現且必須要掌握的知識點

堅持不懈,必能成功。已於21年初加入網易大前端。特來還願。希望看到這篇文章的小夥伴早日實現大廠夢~~~

 

1、mock
在前後端分離的開發中,Mock 數據是前端開發中很重要的一個環節,前端可以不必強依賴後端接口,只需要約定好對應的數據接口,前端可以通過 Mock 模擬數據先行開發,在後端接口開發完成後,只需要切換對應的接口地址即可,可以保證項目的同步開發。

本地內容:在mock文件夾下中的index文件中定義好自有的接口路徑,再到根目錄的service文件夾下生成對應業務模塊的js文件。文件內將相應微服務的接口匹配好。暴露出去供業務功能調用。

2、網絡請求編碼表示
會從你是否關注Request head的哪些內容入手,一般關注點放在statusCode和method上就夠用,重點200,304。同時掌握了基礎後希望注意的點爲文件上傳的內容(百度問過斷點續傳的實現)

200: '服務器成功返回請求的數據。',
201: '新建或修改數據成功。',
202: '一個請求已經進入後臺排隊(異步任務)。',
204: '刪除數據成功。',
304:協商緩存
400: '發出的請求有錯誤,服務器沒有進行新建或修改數據的操作。',
401: '用戶沒有權限(令牌、用戶名、密碼錯誤)。',
403: '用戶得到授權,但是訪問是被禁止的。',
404: '發出的請求針對的是不存在的記錄,服務器沒有進行操作。',
406: '請求的格式不可得。',
410: '請求的資源被永久刪除,且不會再得到的。',
422: '當創建一個對象時,發生一個驗證錯誤。',
500: '服務器發生錯誤,請檢查服務器。',
502: '網關錯誤。',
503: '服務不可用,服務器暫時過載或維護。',
504: '網關超時。'

寫給新手前端的各種文件上傳攻略,從小圖片到大文件斷點續傳 - 掘金​juejin.im

 

3、axios工作流程
axios 是一個基於Promise 用於瀏覽器和 nodejs 的 HTTP 客戶端,本質上也是對原生XHR的封裝,只不過它是Promise的實現版本,符合最新的ES規範,它本身具有以下特徵:

1.從瀏覽器中創建 XMLHttpRequest

2.支持 Promise API

3.客戶端支持防止CSRF

4.提供了一些併發請求的接口(重要,方便了很多的操作)

5.從 node.js /java創建 http 請求

6.攔截請求和響應

7.轉換請求和響應數據

8.取消請求

9.自動轉換JSON數據

防止CSRF:就是讓你的每個請求都帶一個從cookie中拿到的key, 根據瀏覽器同源策略,假冒的網站是拿不到你cookie中得key的,這樣,後臺就可以輕鬆辨別出這個請求是否是用戶在假冒網站上的誤導輸入,從而採取正確的策略。

/**
*
*
* @param {*} params mmsi
* @param {*} callback
*
*
*/
getship_cargo_detail:function(params,callback){
axios.get(server.portAddress+"newshipcargo/newship_pos_detail",{params})
.then(function(res){
callback(res.data);
})
.catch(function(error){
console.log("get_ship_cargo_data_error");
})
},


//調用方法

shipcargoserver.getship_cargo_detail({mmsi:mmsi},data=>{
if(data){
this.setState({
pageNumber:data.,,,,,,,
})
}
})

4、ElementUI(ElementReact)與antdesign和ice-work的比較
使用Element的原因是通過學習餓廠的 Element

其設計原則可以兼容三大框架 (三大框架各有實現):
Vue Element
React Element
Angular Element

整體上 UI 都是一套,但在不同框架中實現方式各異,API 變更較小,如果需要多個框架保持一套風格, Element 是非常好的選擇。爲了減少學習變更後項目api


antdesign功能極強,主要用來學習與觀摩,模仿其語法及代碼風格,主要基於React組件庫的支持。感覺唯一的不足時在於當時使用時缺少一些在線預覽的功能,最近又出了antdvue

飛冰最有意思的是釘釘羣實時答疑讓p7給你答疑(前提是混入羣中)。500+ ICE 使用者在羣裏問任何層級的前端問題
React 組件。基礎組件使用 Fusion,此外根據業務特性等開發了 40+ 業務組件

Playground:可複用模板,用於快速展示效果的業務。

 

5、WebRequest
API 可以讓插件監控 Chrome 的網絡請求,甚至重定向請求。例如:臨時替換hotfix分支的圖片

// background.js
chrome.webRequest.onBeforeRequest.addListener(
function (details) {
const url = details.url;

if (url === 'http://n.sinaimg.cn/news/1_img/upload/7b577cec/576/w778h598/20180820/lSSg-hhxaafy9194151.jpg') {
console.log(22)
return {
redirectUrl: 'https://github.com/welearnmore/chrome-extension-book/raw/master/doc/images/logo_google_developers.png'
}
}

return {cancel: false}
},
{urls: ["<all_urls>"]},
["blocking"]
)

6、減少reflow的方法
不要一條一條地修改 DOM 的樣式。與其這樣,還不如預先定義好 css 的 class,然後修改 DOM 的 className:
// 不好的寫法 var left = 10, top = 10; el.style.left = left + "px"; el.style.top = top + "px"; // 推薦寫法 el.className += " theclassname";
把 DOM 離線後修改。如:
a> 使用 documentFragment 對象在內存裏操作 DOM。
b> 先把 DOM 給 display:none (有一次 repaint),然後你想怎麼改就怎麼改。比如修改 100 次,然後再把他顯示出來。
c>clone 一個 DOM 節點到內存裏,然後想怎麼改就怎麼改,改完後,和在線的那個的交換一下。
不要把 DOM 節點的屬性值放在一個循環裏當成循環裏的變量。不然這會導致大量地讀寫這個結點的屬性。
儘可能的修改層級比較低的 DOM節點。當然,改變層級比較底的 DOM節點有可能會造成大面積的 reflow,但是也可能影響範圍很小。
爲動畫的 HTML 元件使用 fixed 或 absoult 的 position,那麼修改他們的 CSS 是會大大減小 reflow 。
千萬不要使用 table 佈局。因爲可能很小的一個小改動會造成整個 table 的重新佈局。
參考:

人類身份驗證 - SegmentFault​segmentfault.com

深刻剖析迴流與重繪:

你真的瞭解迴流和重繪嗎 - 掘金​juejin.im

7、微任務與宏任務與eventloop
重點記住promise在.then之前是同步任務,.then/.catch/.finally是微任務,執行完同步任務後,在異步中最先執行的就是promise

執行順序:同步任務--->微任務--->宏任務

 

參考

微任務、宏任務與Event-Loop - 賈順名 - 博客園​www.cnblogs.com

8、隱式轉換全部情況
!![] == true //結果是true
[] == true //結果是false
![] == [] //結果是true

針對[] == true 與!![]的解釋參考:

https://blog.csdn.net/u014465934/article/details/84642329​blog.csdn.net

記憶方式

[] 轉爲字符串是 "" // String([]) 返回""

[] 轉爲數字是 0 // Number([]) 返回0

[] 轉爲布爾值是 true // Boolean([]) 返回true

true 轉爲數字是 1 // Number(true) 返回1

false 轉爲數字是 0 // Number(false) 返回0

 

參考全部隱式轉化規則

https://blog.csdn.net/qq_42532128/article/details/84940906​blog.csdn.net

 

9、webstorage
着重點在於sessionstorage與localstorage的數據存儲機制及處理機制。

WebStorage是什麼?​www.jianshu.com

 

 

10、如何使用sessionID判別用戶狀態
將cookie中放入響應頭中攜帶相應sessionID通過post方式向後端發請求,後端返回結果爲用戶獨特的sessionID與前端匹配,則不用創建新的sessionID,假若不匹配則需要創建一個新的sessionID,歸根結底還是由於HTTP的無狀態性,web容器生成一個sessionid來標識用戶,以便獲取該用戶對應的session信息。
後臺生成一個新sessionid的可能原因:

這是一個新用戶的第一次請求
後端存在清空session的邏輯
前端沒有將sessionid放到cookie或其他約定的地方傳給後端
前端傳了,但後端沒有匹配到對應的sessionid(如果是個分佈式服務,負載均衡後,後端服務沒有做session同步)

11、OAuth2原理及應用

允許用戶授權第三方移動應用訪問他們存儲在另外的服務提供者上的信息,而不需要將用戶名和密碼提供給第三方移動應用或分享他們數據的所有內容,OAuth2.0是OAuth協議的延續版本,但不向後兼容OAuth 1.0即完全廢止了OAuth1.0。

應用場景:

原生app授權:app登錄請求後臺接口,爲了安全認證,所有請求都帶token信息,如果登錄驗證、請求後臺數據。

前後端分離單頁面應用(spa):前後端分離框架,前端請求後臺數據,需要進行oauth2安全認證,比如使用vue、react後者h5開發的app。

流程:

(A)用戶打開客戶端以後,客戶端要求用戶給予授權。

(B)用戶同意給予客戶端授權。

(C)客戶端使用上一步獲得的授權,向認證服務器申請令牌。

(D)認證服務器對客戶端進行認證以後,確認無誤,同意發放令牌。

(E)客戶端使用令牌,向資源服務器申請獲取資源。

(F)資源服務器確認令牌無誤,同意向客戶端開放資源。

 

12、http://socket.io的前端使用
客戶端和服務器之間的低延遲雙向通信。客戶端應用程序可以使用 Javascript的任何 SocketIO 官方客戶端庫或任何兼容的客戶端來建立與服務器的永久連接。

引入http://socket.io的依賴在react框架中進行使用,自己嘗試實現了一個聊天室:

testconnect=()=>{
let socket = sockjs("ws://localhost:3900", {
transports: ['websocket']
})
// /不間斷嘗試重連接
socket.on('reconnect_attempt',()=> {
console.log("reconnect")
socket.transports = ['websocket','polling', 'flashsocket'];
});

// 重連接時出錯
socket.on('reconnect_error',(attemptNumber)=> {
console.log(attemptNumber)
});

//連接成功走這個方法
socket.on('connect',()=>{
console.log(socket.connected)
})

//報錯時走這個方法
socket.on('connect_error', (error) => {
console.log(error)
});

//連接存活驗證
socket.on('ping', (error) => {
console.log('ping_include')
});
// 連接成功的connect方法
socket.on("connect",function(){
// console.log(socket.broadcast)
socket.emit('join',prompt('what is your nickname'));
$('#chat').css('display','block');

socket.on('announcement',(msg)=>{
if(msg){
console.log("announcement did right")
let li = `<li class="announcement">${msg}</li>`
$("#messages").append(li);
}
})
})
// 添加獲取信息的方法

$("#form").submit(()=>{
let inputan =$('#input');
console.log("submit success")
this.addmessage('me',inputan.val()) ;
socket.emit('text',inputan.val());

inputan.attr('value');
inputan.focus();

return false
} )
//不要自執行,要在調用後再執行
socket.on('text',this.addmessage)
}
// 將聊天記錄添加到首頁的每一個字段上
addmessage=(from,text)=>{
if(text){
let li = `<li class="message"><b>${from}</b>:${text}</li>`
$("#messages").append(li);
}
}

13、webpack的作用及核心配置
webpack配置中需要理解幾個核心的概念Entry 、Output、Loaders 、Plugins、 Chunk

Entry:指定webpack開始構建的入口模塊,從該模塊開始構建並計算出直接或間接依賴的模塊或者庫
Output:告訴webpack如何命名輸出的文件以及輸出的目錄
Loaders:由於webpack只能處理javascript,所以我們需要對一些非js文件處理成webpack能夠處理的模塊,比如sass文件
Plugins:Loaders將各類型的文件處理成webpack能夠處理的模塊,plugins有着很強的能力。插件的範圍包括,從打包優化和壓縮,一直到重新定義環境中的變量。但也是最複雜的一個。比如對js文件進行壓縮優化的UglifyJsPlugin插件
Chunk:coding split的產物,我們可以對一些代碼打包成一個單獨的chunk,比如某些公共模塊,去重,更好的利用緩存。或者按需加載某些功能模塊,優化加載時間。在webpack3及以前我們都利用CommonsChunkPlugin將一些公共代碼分割成一個chunk,實現單獨加載。在webpack4 中CommonsChunkPlugin被廢棄,使用SplitChunksPlugin

webpack詳解 - 掘金​juejin.im

 

webpack打包原理解析​www.jianshu.com

進階(具備手擼一個loader、plugins的能力):

乾貨!擼一個webpack插件(內含tapable詳解+webpack流程) - 掘金​juejin.im

手把手教你擼一個 Webpack Loader​juejin.im

14、==與===的比較,===的使用情況
===的使用情況我回答是,一般在比較字符串時來使用。

權威解釋:

理清JS中等於(==)和全等(===)那些糾纏不清的關係 - 掘金​juejin.im

15、閉包的應用場景
函數防抖,通過立即執行函數在循環中的異步執行能夠取到正確的值

權威解答:

閉包實際場景應用 - 掘金​juejin.im

16、敏捷開發的全部流程
每次迭代都必須依次完成以下五個步驟。

需求分析(requirements analysis)
設計(design)
編碼(coding)
測試(testing)
部署和評估(deployment / evaluation)
每個迭代大約持續2~6周。

敏捷開發入門教程 - 阮一峯的網絡日誌​www.ruanyifeng.com

17、webpack+glup/FIS
gulp是基於流的自動化構建工具,但不包括模塊化的功能,如果要用到的話,就需要引入外部文件,比如require.js等;而webpack是自動化模塊打包工具,本身就具有模塊化,並且也具有壓縮合並的功能。

【簡單理解】gulp和webpack的區別 - MaxLucio - 博客園​www.cnblogs.com

三者的比較

定位不同,webpack定位是一個打包工具,模塊化。其實自動化的工具更好用gulp之類解決。fis3直接定位爲一個全功能工具,官方文檔介紹中:解決性能優化,模塊化,自動化,甚至包括代碼規範,部署等問題。

個人喜歡用webpack,可以更靈活的搭配其它工具使用,且生態系統強大,當然最近比較火的可能是rollup,它打包的文件體積更小。glup+webpack自動化部署參考:

https://www.cnblogs.com/axl234/p/5845606.html​www.cnblogs.com

18、git常用的基本命令
最最基礎的去參考我自己的文章,進階版看這篇

git基本操作,一篇文章就夠了! - 掘金​juejin.im

19、jar包查看項目進程
到xxx.jar目錄下執行:
nohup java -jar xxx.jar > people.log 2>&1 & -- 運行jar包幷包日誌寫入到people.log中
tail -f people.log --查看運行日誌

 

20、mvc與mvvm的區別
mvc

Model(模型)

View(視圖)

Controller(控制器)

簡單的理解:視圖請求數據,將請求發送至控制器,控制器再將請求發送給模型,模型去查找數據,找到之後傳給控制器,控制器再傳給視圖進行渲染。

mvvm

Model 代表數據模型

View 代表UI視圖

ViewModel 負責監聽 Model 中數據的改變並且控制視圖的更新(橋樑,可以理解成mvc中的控制器) 簡單理解:視圖請求數據,將請求發送至控制器,在控制器的兩端具有監聽機制,直接調用模型的數據,一端改變全部改變,利用數據劫持,結合訂閱者和發佈者模式,實現數據的雙向綁定

mvvm優點

MVVM比MVC精簡很多,不僅簡化了業務與界面的依賴,還解決了數據頻繁更新的問題,不用再用選擇器操作DOM元素。因爲在MVVM中,View不知道Model的存在,Model和ViewModel也觀察不到View,這種低耦合模式提高代碼的可重用性


雙向綁定的定義

一般只有UI表單控件才存在雙向數據綁定,非UI表單控件只有單向數據綁定。
單向數據綁定是指:M的變化可以自動更新到ViewModel,但ViewModel的變化需要手動更新到M(通過給表單控件設置事件監聽)
雙向數據綁定是指念:M的變化可以自動更新到ViewModel,ViewModel的變化也可以自動更新到M
雙向綁定 = 單向綁定 + UI事件監聽。雙向和單向只不過是框架封裝程度上的差異,本質上兩者是可以相互轉換的。
優缺點:在表單交互較多的情況下,單向數據綁定的優點是數據更易於跟蹤管理和維護,缺點是代碼量較多比較囉嗦,雙向數據綁定的優缺點和單向綁定正好相反。

理解MVVM在react、vue中的使用 - _林沖 - 博客園​www.cnblogs.com

MVVM模式在react中的對應關係

M(odel):對應組件的方法或生命週期函數中實現的業務邏輯和this.state中保存的本地數據,如果React集成了redux +react-redux,那麼組件中的業務邏輯和本地數據可以完全被解耦出來單獨存放當做M層,如業務邏輯放在Reducer和Action中。
V(iew)-M(odel):對應組件中的JSX,它實質上是Virtual DOM的語法糖。React負責維護 Virtual DOM以及對其進行diff運算,而React-dom 會把Virtual DOM渲染成瀏覽器中的真實DOM
View:對應框架在瀏覽器中基於虛擬DOM生成的真實DOM(並不需要我們自己書寫)以及我們書寫的CSS
綁定器:對應JSX中的命令以及綁定的數據,如className={ http://this.props.xxx }、{http://this.props.xxx}等等

21、html語義化,css模塊化
就是儘可能的理解要表達的內容,選擇適合的標籤,將內容轉換成瀏覽器認識的語言,通過瀏覽器傳達給用戶。從這個角度來說,我們更像是“翻譯”。

除了專業的人外,沒人會去看我們的標籤是否使用得有語義
HTML的標籤還不足以表達所有可能的語義
語義化會需要增加一些額外的代碼
HTML5新增的幾個標籤,更多的補充了目前HTML標籤語義上的不足,這點也可以看出語義化是以後發展的一個方向,當然更大的目標是統一的實現標準,語義化只是爲了這個目標所使用的一個方法。這可能需要相當的一段時間,而我們正經歷着這個過程。

模塊化

模塊化就是爲了減少循環依賴,減少耦合,提高設計的效率。爲了做到這一點,我們需要有一個設計規則,所有的模塊都在這個規則下進 行設計。良好的設計規則,會把耦合密集的設計參數進行歸類作爲一個模塊,並以此劃分工作任務。而模塊之間彼此通過一個固定的接口(所謂的可見參數)進行交互,除此之外的內部實現(所謂的隱參數)則由模塊的開發團隊進行自由發揮。

程序模塊化的目的:

1.減少循環依賴

2.減少耦合

3.提高設計效率

css模塊化原則

分離結構和表現
分離容器和內容
22、標準化的javascript
JavaScript 的核心 ECMAScript 描述了該語言的語法和基本對象;
DOM 描述了處理網頁內容的方法和接口;
BOM 描述了與瀏覽器進行交互的方法和接口。

23、前端兼容性問題總結
瀏覽器兼容性問題解決方案 · 總結​juejin.im

24、前端性能優化
前端性能優化的常用手段 - 掘金​juejin.im

25、loadash的使用
Lodash中十個常用的工具函數 - Web前端 - ITeye資訊​www.iteye.com

26、前端預處理器sass的使用
Sass 是一款強化 CSS 的輔助工具,它在 CSS 語法的基礎上增加了變量 (variables)、嵌套 (nested rules)、混合 (mixins)、導入 (inline imports) 等高級功能,這些拓展令 CSS 更加強大與優雅。使用 Sass 以及 Sass 的樣式庫(如 Compass)有助於更好地組織管理樣式文件,以及更高效地開發項目。

CSS預處理器之sass的用法 - 掘金​juejin.im

27、leetcode算法最優解
找不到想要的解答,從這上面搜一下

九章算法 - 幫助更多中國人找到好工作,硅谷頂尖IT企業工程師實時在線授課爲你傳授面試技巧​www.jiuzhang.com

28、不瞭解的三種函數寫法
https://blog.csdn.net/Prince_fmx/article/details/77864310​blog.csdn.net

一篇文章搞懂toString()和valueOf() - html/css語言欄目:html.css - 紅黑聯盟​www.2cto.com

29、react源碼總結
React源碼學習小結​www.jianshu.com

react在使用時總結不出這麼多優點,他幫你解決了面試提問的難題:

React精髓!一篇全概括(急速) - 掘金​juejin.im

 

30、Flex佈局,position,垂直水平居中三種必問前端常識
http://www.ruanyifeng.com/blog/2015/07/flex-examples.html​www.ruanyifeng.com

31、破碎浮點型數據的解決辦法
過長的純數字數組不能通過Number或者parseInt進行轉化,這樣會產生錯誤,要使用BigInt來解決。想要計算二元運算需要在二元運算的另一個項上加上n,參考例子與講解均在裏面:

js基本數據類型 BigInt 和 Number 的區別​cloud.tencent.com

32、中級前端所有手寫內容
防抖、節流
深淺拷貝
數組亂序、數組去重(各種時間空間複雜度)
數組filter
數組flat(平展一層到多層)
手寫call、bind、apply(及瞭解這三種的區別)
八種繼承及各種繼承之間的特點
實現instanceof
實現new的過程
lazyman
jsonp的實現
函數的柯力化
promise、promise.all、promise.retry
(其中大廠不排除讓你手寫ajax的封裝(百度),頭條(promise.retry))
參考地址:
“寒冬”三年經驗前端面試總結(含頭條、百度、餓了麼、滴滴等)之手寫題(一) - 掘金​juejin.im

 

“寒冬”三年經驗前端面試總結(含頭條、百度、餓了麼、滴滴等)之手寫題(二) - 掘金​juejin.im

 

實現promise.all方法 - 掘金​juejin.im

 

33、大廠常問的React全家桶
必須掌握、必須掌握、必須掌握!

react-router:

2. React-Router的基本使用​juejin.im

 

redux、react-redux:

一篇文章總結redux、react-redux、redux-saga - 掘金​juejin.im

 

拓展(強烈建議能手寫出來)、幾家大廠都在問:

讓react用起來更得心應手--(react-router原理簡析) - 掘金​juejin.im

 

 

34、三分鐘記牢原型,原型鏈,繼承

 

 


function Animal(){
this.type = "animal";
}
Animal.prototype.getType = function(){
return this.type;
}

function Dog(){
this.name = "dog";
}
Dog.prototype = new Animal();

Dog.prototype.getName = function(){
return this.name;
}

var xiaohuang = new Dog();
//原型鏈關係
xiaohuang.__proto__ === Dog.prototype
Dog.prototype.__proto__ === Animal.prototype
Animal.prototype.__proto__ === Object.prototype
Object.prototype.__proto__ === null

35、解釋下Promise與Promise.all及擴展
promise是什麼?
Promise是異步編程的一種解決方案,比傳統的回調函數和事件更合理和強大。
所謂Promise,簡單來說就是一個容器,裏面保存着某個未來纔會結束的事情(通常是一個異步操作)。從語法上說,Promise是一個對象,從他可以獲取異步操作的消息。

特質:

一:對象的狀態不受外部影響

二:一旦狀態改變,就無法再被改變。

缺點:

一旦創建promise就會立即執行

使用:
const newPromise = new promise((resolve,reject)=>{
if(success){
resolve()
}else{
reject()
}
}).then((data)=>{console.log(data)},(error)=>{console.log(error})
.catch(null,(error)=>{console.log(error)})
then方法可以接受兩個回調函數作爲參數,

第一個回調函數是promise對象的狀態變爲resolved的時候調用,

第二個回調函數是promise對象的狀態變爲rejected時調用。

其中第二個函數是可選的,不一定需要提供。

catch方法是.then(null, rejection)的別名,用於指定發生錯誤時的回調函數。

 

promise.all是什麼?

Promise.all(iterable) 方法返回一個 Promise 實例,此實例在 iterable 參數內所有的 promise 都“完成(resolved)”或參數中不包含 promise 時回調完成(resolve);如果參數中 promise 有一個失敗(rejected),此實例回調失敗(reject),失敗原因的是第一個失敗 promise 的結果。

result = arr.map(i => {
...
const rowPromise = filtered
.sort({ create_time: -1 }) //-1降序 1升序
.skip(offset > -1 ? offset : 0)
.limit(limit <= 200000 ? limit : 200000)
.toArray()
return rowPromise
})

promise.all(result)
.then(total => resolve(total))
.catch(err => reject(err))
promise.all中傳入的result一定要是一個數組。返回的是個promise實例,機制與promise一致

詳細的promise.all&promise.race參考

神奇的Aym:面試問到 Promise,這樣回答最完美了​zhuanlan.zhihu.com

36、ES6中export與export default差異總結
export default在一個模塊中只能有一個,但是export可以有多個。
通過export導出的(屬性或者方法)可以修改,但是通過export default導出的是不可修改的。
export var e1='...' 是合法語句,但是export default var e2='...'是不合法的(let和const也一樣)。
export default可以直接添加標識符導出,例如export default e2;export如果要導出已經聲明的表示符,必須使用{},例如export {e1},注意:這裏{}不是聲明一個對象。
ES6中模塊通過export和export default暴露出來的屬性或者方式並不是普通的賦值或者引用,它們是對模塊內部定義的標誌符類似指針的綁定。
對於一個導出的屬性或者方法,在什麼地方導出不重要,在什麼時候導入也不重要,重要的是:訪問這這個綁定的時候的當前值。
ES6 export && export default 差異總結​juejin.im

37、簡述Generator函數的基本語法
Generator (生成器)函數有多種理解角度。語法上,首先可以把它理解成,Generator 函數是一個狀態機,封裝了多個內部狀態。執行 Generator 函數會返回一個遍歷器對象。

特徵一:function關鍵字與函數名之間有一個號(*寫在之間的任何位置都可以通過,不區分有幾個空格)

特徵二:函數體內有yield(產出)表達式,定義了不同的內部狀態

function* helloWorldGenerator() {
yield 'hello';
yield 'world';
return 'ending';
}

var hw = helloWorldGenerator();
hw.next()
// { value: 'hello', done: false }

hw.next()
// { value: 'world', done: false }

hw.next()
// { value: 'ending', done: true }

hw.next()
// { value: undefined, done: true }
函數執行.next()後返回的也不是函數運行結果,而是一個指向內部狀態的指針對象。每次調用next方法,內部指針就從函數頭部或上一次停下來的地方開始執行,直到遇到下一個yield表達式(或return語句)爲止。換言之,Generator 函數是分段執行的,yield表達式是暫停執行的標記,而next方法可以恢復執行。

function* gen() {
yield 123 + 456;
}
上面代碼中,yield後面的表達式123 + 456,不會立即求值,只會在next方法將指針移到這一句時,纔會求值。

yield表達式與return語句既有相似之處,也有區別。相似之處在於,都能返回緊跟在語句後面的那個表達式的值。區別在於每次遇到yield,函數暫停執行,下一次再從該位置繼續向後執行,而return語句不具備位置記憶的功能。一個函數裏面,只能執行一次(或者說一個)return語句,但是可以執行多次(或者說多個)yield表達式。正常函數只能返回一個值,因爲只能執行一次return;Generator 函數可以返回一系列的值,因爲可以有任意多個yield。

for...of循環,擴展運算符(...)、解構賦值和Array.from方法內部調用的,都是遍歷器接口。這意味着,它們都可以將 Generator 函數返回的 Iterator 對象,作爲參數

function* numbers () {
yield 1
yield 2
return 3
yield 4
}

// 擴展運算符
[...numbers()] // [1, 2]

// Array.from 方法
Array.from(numbers()) // [1, 2]

// 解構賦值
let [x, y] = numbers();
x // 1
y // 2

// for...of 循環
for (let n of numbers()) {
console.log(n)
}
// 1
// 2
https://es6.ruanyifeng.com/#docs/generator-async​es6.ruanyifeng.com

38、錯誤邊界(Error Boundaries)
部分 UI 的 JavaScript 錯誤不應該導致整個應用崩潰,爲了解決這個問題,React 16 引入了一個新的概念 —— 錯誤邊界。

錯誤邊界是一種 React 組件,這種組件可以捕獲並打印發生在其子組件樹任何位置的 JavaScript 錯誤,並且,它會渲染出備用 UI,而不是渲染那些崩潰了的子組件樹。錯誤邊界在渲染期間、生命週期方法和整個組件樹的構造函數中捕獲錯誤。

如果一個 class 組件中定義了

static getDerivedStateFromError()

componentDidCatch()

這兩個生命週期方法中的任意一個(或兩個)時,那麼它就變成一個錯誤邊界。當拋出錯誤後,請使用 static getDerivedStateFromError() 渲染備用 UI ,使用 componentDidCatch() 打印錯誤信息。

class ErrorBoundary extends React.Component {
constructor(props) {
super(props);
this.state = { hasError: false };
}

static getDerivedStateFromError(error) {
// 更新 state 使下一次渲染能夠顯示降級後的 UI
return { hasError: true };
}
componentDidCatch(error, errorInfo) {
// 你同樣可以將錯誤日誌上報給服務器
logErrorToMyService(error, errorInfo);
}
render() {
if (this.state.hasError) { // 你可以自定義降級後的 UI 並渲染 return <h1>Something went wrong.</h1>; }
return this.props.children;
}
}
錯誤邊界的工作方式類似於 JavaScript 的 catch {},不同的地方在於錯誤邊界只針對 React 組件。只有 class 組件纔可以成爲錯誤邊界組件。大多數情況下, 你只需要聲明一次錯誤邊界組件, 並在整個應用中使用它。

注意錯誤邊界僅可以捕獲其子組件的錯誤,它無法捕獲其自身的錯誤。如果一個錯誤邊界無法渲染錯誤信息,則錯誤會冒泡至最近的上層錯誤邊界,這也類似於 JavaScript 中 catch {} 的工作機制。

自 React 16 起,任何未被錯誤邊界捕獲的錯誤將會導致整個 React 組件樹被卸載。

在開發環境下,React 16 會把渲染期間發生的所有錯誤打印到控制檯,即使該應用意外的將這些錯誤掩蓋。除了錯誤信息和 JavaScript 棧外,React 16 還提供了組件棧追蹤。現在你可以準確地查看發生在組件樹內的錯誤信息:

 

注意

錯誤邊界 無法捕獲以下場景中產生的錯誤:
事件處理(瞭解更多)
異步代碼(例如 setTimeout 或 requestAnimationFrame 回調函數)
服務端渲染
它自身拋出來的錯誤(並非它的子組件)

39、null與undefiend的區別
大多數計算機語言,有且僅有一個表示"無"的值,比如,C語言的NULL,Java語言的null,Python語言的None,Ruby語言的nil。

有點奇怪的是,JavaScript語言居然有兩個表示"無"的值:undefined和null。

null表示"沒有對象",即該處不應該有值。典型用法是:

(1) 作爲函數的參數,表示該函數的參數不是對象。
(2) 作爲對象原型鏈的終點。

Object.getPrototypeOf(Object.prototype) // null
undefined表示"缺少值",就是此處應該有一個值,但是還沒有定義。典型用法是:

(1)變量被聲明瞭,但沒有賦值時,就等於undefined。
(2) 調用函數時,應該提供的參數沒有提供,該參數等於undefined。
(3)對象沒有賦值的屬性,該屬性的值爲undefined。
(4)函數沒有返回值時,默認返回undefined。
var i;
i // undefined

function f(x){console.log(x)}
f() // undefined

var o = new Object();
o.p // undefined

var x = f();
x // undefined

40、探究Function.__proto__===Function.prototype(自己生成自己)
對象類型的成員,標準內置構造器 Function的一個實例,並且可做爲子程序被調用。

注: 函數除了擁有命名的屬性,還包含可執行代碼、狀態,用來確定被調用時的行爲。函數的代碼不限於 ECMAScript。

目前存在三種創建函數的形式

demo instanceof Function
//true
上面只是創建函數的一種方式, JavaScript 中有三種創建形式,分別是:
①聲明式

function fn(){ }; //這種定義的方式,無論在哪兒定義,別處都可以調用 ;
②函數的字面量或叫直接量或稱表達式

var fn=function () { }; //此時函數作爲表達式存在,調用只能在定義的後面;
//解釋一下表達式:凡是將數據和運算符等聯繫起來有值得式子就是表達式。
③以new Function 的形式

var fn = new Function (arg1 , arg2 ,arg3 ,…, argN , body)
/*Function 構造函數所有的參數都是字符串類型。除了最後一個參數, 其餘的參數都作爲生成函數的參數即形參。
這裏可以沒有參數。最後一個參數, 表示的是要創建函數的函數體。

使用Function構造器生成的Function對象是在函數創建時解析的。這比你使用函數聲明或者函數表達式(function)
並在你的代碼中調用更爲低效,因爲使用後者創建的函數是跟其他代碼一起解析的。
*/

問題引出
我們知道,Array,Date,Number,String,Boolean,Error甚至Object都是Function的一個實例,那麼Function是誰的實例呢?

Function構造函數的prototype屬性和__proto__屬性都指向同一個原型,是否可以說Function對象是由Function構造函數創建的一個實例?

Function.prototype和Function.__proto__都指向Function.prototype,因此function對象又是Function構造函數創建的實例。

Function 和 Object 和其它構造函數繼承 Function.prototype 而產生。

先有 Object.prototype,再有 Object

Function.proto=== Function.prototype;
Function 構造函數的 prototype 屬性和__proto__屬性都指向同一個原型,可以說 Function 對象是由 Function 構造函數創建的一個實例
Object instanceof Function // true
Function instanceof Object // true
Object 本身是構造函數,繼承了 Function.prototype;Function 也是對象,繼承了 Object.prototype。

function Person(){}
Person.prototype 是一個對象,Function.prototype 卻是一個函數
結論:

在使用聲明式 function的時候其實已經幫你做了new Function()這一步了,function和new Function()創建的函數都是Function的一個實例,只是方式不一樣,其實本質都是一樣。

 

明天一定會感謝今天努力的自己!
————————————————
版權聲明:本文爲CSDN博主「&amp;時光」的原創文章,遵循CC 4.0 BY-SA版權協議,轉載請附上原文出處鏈接及本聲明。
原文鏈接:https://blog.csdn.net/Time_Flies_lei/article/details/116568760

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章