前端成長進(jìn)階指北(JS篇)
點(diǎn)擊上方 三分鐘學(xué)前端,關(guān)注公眾號(hào)
回復(fù)交流,加入前端編程面試算法每日一題群
嗨!各位早上好,三分鐘學(xué)前端來一波第一季度回顧與總結(jié),今天主講 JS 篇 ,且已整理成了 pdf ,文末免費(fèi)獲取
下面進(jìn)入正文吧??
indexOf 和 findIndex 的區(qū)別
indexOf:查找值作為第一個(gè)參數(shù),采用===比較,更多的是用于查找基本類型,如果是對象類型,則是判斷是否是同一個(gè)對象的引用findIndex:比較函數(shù)作為第一個(gè)參數(shù),多用于非基本類型(例如對象)的數(shù)組索引查找,或查找條件很復(fù)雜
閉包 JS基礎(chǔ) 編程題 (字節(jié))
var foo = function(...args) {
// 要求實(shí)現(xiàn)函數(shù)體
}
var f1 = foo(1,2,3);
f1.getValue(); // 6 輸出是參數(shù)的和
var f2 = foo(1)(2,3);
f2.getValue(); // 6
var f3 = foo(1)(2)(3)(4);
f3.getValue(); // 10
解答@Ishmael-Yoko
function foo(...args) {
const target = (...arg1s) => foo(...[...args, ...arg1s])
target.getValue = () => args.reduce((p, n) => p+ n, 0)
return target
}
閉包的使用場景,使用閉包需要注意什么

了解詞法環(huán)境嗎?它和閉包有什么聯(lián)系?
一個(gè)函數(shù)和對其周圍狀態(tài)(lexical environment,詞法環(huán)境)的引用捆綁在一起(或者說函數(shù)被引用包圍),這樣的組合就是閉包(closure)
也就是說,閉包是由 函數(shù) 以及聲明該函數(shù)的 詞法環(huán)境 組合而成的
了解詞法環(huán)境嗎?它和閉包有什么聯(lián)系?
從頁面 A 打開一個(gè)新頁面 B,B 頁面關(guān)閉(包括意外崩潰),如何通知 A 頁面?
本題是 html 頁面通信題,可以拆分成:
A 頁面打開 B 頁面,A、B 頁面通信方式? B 頁面正常關(guān)閉,如何通知 A 頁面? B 頁面意外崩潰,又該如何通知 A 頁面?
從頁面 A 打開一個(gè)新頁面 B,B 頁面關(guān)閉(包括意外崩潰),如何通知 A 頁面?
監(jiān)聽一個(gè)變量的變化,需要怎么做
監(jiān)聽一個(gè)變量的變化,當(dāng)變量變化時(shí)執(zhí)行某些操作,這類似現(xiàn)在流行的前端框架(例如 React、Vue等)中的數(shù)據(jù)綁定功能,在數(shù)據(jù)更新時(shí)自動(dòng)更新 DOM 渲染,那么如何實(shí)現(xiàn)數(shù)據(jù)綁定喃?
本文給出兩種思路:
ES5 的 Object.defineProperty ES6 的 Proxy Proxy 相比于 defineProperty 的優(yōu)勢:
基于 Proxy和Reflect,可以原生監(jiān)聽數(shù)組,可以監(jiān)聽對象屬性的添加和刪除不需要深度遍歷監(jiān)聽:判斷當(dāng)前 Reflect.get的返回值是否為Object,如果是則再通過reactive方法做代理, 這樣就實(shí)現(xiàn)了深度觀測只在 getter時(shí)才對對象的下一層進(jìn)行劫持(優(yōu)化了性能)所以,建議使用
Proxy監(jiān)測變量變化
講下 V8 sort 的大概思路,并手寫一個(gè) sort 的實(shí)現(xiàn)
關(guān)于
Array.prototype.sort(),ES 規(guī)范并沒有指定具體的算法,在 V8 引擎中, 7.0 版本之前 ,數(shù)組長度小于10時(shí),Array.prototype.sort()使用的是插入排序,否則用快速排序。在 V8 引擎 7.0 版本之后 就舍棄了快速排序,因?yàn)樗皇欠€(wěn)定的排序算法,在最壞情況下,時(shí)間復(fù)雜度會(huì)降級(jí)到 O(n2)。
于是采用了一種混合排序的算法:TimSort 。

講下 V8 sort 的大概思路,并手寫一個(gè) sort 的實(shí)現(xiàn)
了解繼承嗎?該如何實(shí)現(xiàn)繼承?
JS 繼承主要由六種實(shí)現(xiàn)方式:
原型鏈繼承 構(gòu)造函數(shù)繼承 組合繼承 寄生組合繼承 原型式繼承 ES6 繼承
什么變量保存在堆/棧中?
JS 就是動(dòng)態(tài)語言,因?yàn)樵诼暶髯兞恐安⒉恍枰_認(rèn)其數(shù)據(jù)類型,所以 JS 的變量是沒有數(shù)據(jù)類型的,值才有數(shù)據(jù)類型,變量可以隨時(shí)持有任何類型的數(shù)據(jù)。
JS 值有 8 種數(shù)據(jù)類型,它們可以分為兩大類——基本類型和引用類型。其中,基本類型的數(shù)據(jù)是存放在棧中,引用類型的數(shù)據(jù)是存放在堆中的。堆中的數(shù)據(jù)是通過引用和變量關(guān)聯(lián)起來的。
閉包除外,JS 閉包中的變量值并不保存中棧內(nèi)存中,而是保存在堆內(nèi)存中。
實(shí)現(xiàn)顏色轉(zhuǎn)換 'rgb(255, 255, 255)' -> '#FFFFFF' 的多種思路
仔細(xì)觀察本題,本題可分為三個(gè)步驟:
從 rgb(255, 255, 255)中提取出r=255、g=255、b=255將 r、g、b轉(zhuǎn)換為十六進(jìn)制,不足兩位則補(bǔ)零組合 #
實(shí)現(xiàn)顏色轉(zhuǎn)換 'rgb(255, 255, 255)' -> '#FFFFFF' 的多種思路
實(shí)現(xiàn)一個(gè)異步求和函數(shù)
簡化:兩數(shù)之和
加深:多數(shù)之和
優(yōu)化:使用 Promise.all
一道字節(jié)筆試題,實(shí)現(xiàn)一個(gè)異步求和函數(shù)
一道騰訊手寫題,如何判斷 url 中只包含 qq.com
http://www.qq.com // 通過
http://www.qq.com.cn // 不通過
http://www.qq.com/a/b // 通過
http://www.qq.com?a=1 // 通過
http://www.123qq.com?a=1 // 不通過
由一道bilibili面試題看Promise異步執(zhí)行機(jī)制
Promise構(gòu)造函數(shù)是同步執(zhí)行的,then方法是異步執(zhí)行的.then或者.catch的參數(shù)期望是函數(shù),傳入非函數(shù)則會(huì)直接執(zhí)行Promise的狀態(tài)一經(jīng)改變就不能再改變,構(gòu)造函數(shù)中的resolve或reject只有第一次執(zhí)行有效,多次調(diào)用沒有任何作用.then方法是能接收兩個(gè)參數(shù)的,第一個(gè)是處理成功的函數(shù),第二個(gè)是處理失敗的函數(shù),再某些時(shí)候你可以認(rèn)為catch是.then第二個(gè)參數(shù)的簡便寫法當(dāng)遇到 promise.then時(shí), 如果當(dāng)前的Promise還處于pending狀態(tài),我們并不能確定調(diào)用resolved還是rejected,只有等待promise的狀態(tài)確定后,再做處理,所以我們需要把我們的兩種情況的處理邏輯做成callback放入promise的回調(diào)數(shù)組內(nèi),當(dāng)promise狀態(tài)翻轉(zhuǎn)為resolved時(shí),才將之前的promise.then推入微任務(wù)隊(duì)列
攜程&蘑菇街&bilibili:手寫數(shù)組去重、扁平化函數(shù)
es6 及 es6+ 的能力集,你最常用的,這其中最有用的,都解決了什么問題
我最常用的
ES6 的特性是使用最多的,包括類、模塊化、箭頭函數(shù)、函數(shù)參數(shù)默認(rèn)值、模板字符串、解構(gòu)賦值、延展操作符、Promise、let 與 const等等,這部分已經(jīng)是開發(fā)必備了,沒什么好說的
另外還有:
ES7 的 Array.prototype.includes()ES8 的 async/await 、String padding: padStart()和padEnd()、Object.values()ES9 的 Rest/Spread 屬性、for await of、 Promise.finally()ES10 的 Array.prototype.flat()、Array.prototype.flatMap()、String的trimStart()trimEnd()ES11 的 Promise.allSettled、空值處理(??)及可選鏈(?.)ES12 的邏輯賦值操作符( ||=、&&=、??=)、數(shù)字分隔符(1_000_000_000)、Promise.any()最有用的
ES6 的特性都很有用,ES7-ES11中,我比較感興趣的是:
ES8 的 async/await ES9 的 for await of ES11 的 Promise.allSettled、ES9 的Promise.finally()、ES12 的Promise.any()還有常用的邏輯操作:邏輯賦值操作符、數(shù)字分隔符、空值處理及可選鏈等都很大的簡潔優(yōu)化了我們的代碼 其中,async/await 異步終極解決方案,
for await of異步串行,Promise.allSettled解決了Promise.all的只要一個(gè)請求失敗了就會(huì)拋出錯(cuò)誤的問題,當(dāng)我們一次發(fā)起多個(gè)請求時(shí),所有結(jié)果都能返回,無論成功或失敗,等等等,不了解的可以往下查找
es6 及 es6+ 的能力集,你最常用的,這其中最有用的,都解決了什么問題
Promise.allSettled 的作用,如何自己實(shí)現(xiàn) Promise.allSettled
本文從四個(gè)方面循序漸進(jìn)介紹
Promise.allSettled:
Promise.all()的缺陷引入 Promise.allSettled()Promise.allSettled()與Promise.all()各自的適用場景手寫 Promise.allSettled()實(shí)現(xiàn)
Promise.allSettled 的作用,如何自己實(shí)現(xiàn)一個(gè) Promise.allSettled
Promise.any 的作用,如何自己實(shí)現(xiàn) Promise.any
本文從五個(gè)方面介紹
Promise.any:
Promise.any的作用Promise.any應(yīng)用場景Promise.anyvsPromise.allPromise.anyvsPromise.race手寫 Promise.any實(shí)現(xiàn)
Promise.any 的作用,如何自己實(shí)現(xiàn)一個(gè) Promise.any
Promise.prototype.finally 的作用,如何自己實(shí)現(xiàn) Promise.prototype.finally
Promise.prototype.finally()是 ES2018 新增的特性,它回一個(gè)Promise,在promise結(jié)束時(shí),無論Promise運(yùn)行成功還是失敗,都會(huì)運(yùn)行finally,類似于我們常用的try {...} catch {...} finally {...}
Promise.prototype.finally 的作用,如何自己實(shí)現(xiàn) Promise.prototype.finally
typeof 可以判斷哪些類型?instanceof 做了什么?null為什么被typeof錯(cuò)誤的判斷為了'object'
typeof操作符唯一的目的就是檢查數(shù)據(jù)類型,但我們使用typeof來判斷引用類型變量時(shí),無論是什么類型的變量,它都會(huì)返回Object。為此,引入了instanceof。
instanceof與typeof相比,instanceof方法要求開發(fā)者明確的確認(rèn)對象為某特定類型。即instanceof用于判斷引用類型屬于哪個(gè)構(gòu)造函數(shù)的方法。
typeof 可以判斷哪些類型?instanceof 做了什么?null為什么被typeof錯(cuò)誤的判斷為了'object'
var、let、const 有什么區(qū)別
從作用域規(guī)則、重復(fù)聲明/重復(fù)賦值、變量提升(hoisted)、暫時(shí)死區(qū)(TDZ)四個(gè)方面對比
var、let、const聲明的變量差異
WeakMap 和 Map 的區(qū)別,WeakMap 原理,為什么能被 GC?
Map相對于WeakMap:
Map的鍵可以是任意類型,WeakMap只接受對象作為鍵(null除外),不接受其他類型的值作為鍵Map的鍵實(shí)際上是跟內(nèi)存地址綁定的,只要內(nèi)存地址不一樣,就視為兩個(gè)鍵;WeakMap的鍵是弱引用,鍵所指向的對象可以被垃圾回收,此時(shí)鍵是無效的Map可以被遍歷,WeakMap不能被遍歷
WeakMap 和 Map 的區(qū)別,WeakMap 原理,為什么能被 GC?
更多
實(shí)現(xiàn)一個(gè) sleep 函數(shù),可從 Promise、Generator、Async/Await 等角度實(shí)現(xiàn)
面試官問:Promise.all 使用、原理實(shí)現(xiàn)及錯(cuò)誤處理
實(shí)現(xiàn)一個(gè)方法,拆解URL參數(shù)中queryString
介紹 setTimeout 實(shí)現(xiàn)機(jī)制與原理,手寫一個(gè)實(shí)現(xiàn)
字節(jié):如何模擬實(shí)現(xiàn) new 操作符
前端同學(xué)經(jīng)常忽視的一個(gè) JavaScript 面試題
手寫 LRU 緩存策略,了解 Vue 的 keep-alive 實(shí)現(xiàn)
介紹下 Set、Map、WeakSet 和 WeakMap 的區(qū)別?
用最簡潔代碼實(shí)現(xiàn) indexOf 方法
給定兩個(gè)數(shù)組,寫一個(gè)方法來計(jì)算它們的交集
什么是防抖和節(jié)流?有什么區(qū)別?如何實(shí)現(xiàn)?
JS數(shù)組中 forEach() 和 map() 的區(qū)別
實(shí)現(xiàn)一個(gè)數(shù)組(包含對象等類型元素)去重函數(shù)
不產(chǎn)生新數(shù)組,刪除數(shù)組里的重復(fù)元素
攜程&蘑菇街&bilibili:手寫數(shù)組去重、扁平化函數(shù)
pdf
關(guān)注「三分鐘學(xué)前端」:
回復(fù)「JS」,自動(dòng)獲取三分鐘學(xué)前端 JS 篇小書(120+頁)
回復(fù)「算法」,自動(dòng)獲取 github 2.9k+ 的前端算法小書
回復(fù)「面試」,自動(dòng)獲取 github 23.2k+ 的前端面試小書
回復(fù)「簡歷」,自動(dòng)獲取程序員系列的 120 套模版
最近開源了一個(gè)github倉庫:百問百答,在工作中很難做到對社群問題進(jìn)行立即解答,所以可以將問題提交至 https://github.com/Advanced-Frontend/Just-Now-QA ,我會(huì)在每晚花費(fèi) 1 個(gè)小時(shí)左右進(jìn)行處理,更多的是鼓勵(lì)與歡迎更多人一起參與探討與解答??
