前端開(kāi)發(fā)面試題(溫故而知新)
1、斷點(diǎn)續(xù)傳怎么做的?
答:斷點(diǎn)續(xù)傳是一種網(wǎng)絡(luò)傳輸技術(shù),可以在文件傳輸中出現(xiàn)中斷后恢復(fù)傳輸而無(wú)需重新開(kāi)始傳輸整個(gè)文件。這在文件傳輸較大、網(wǎng)絡(luò)不穩(wěn)定、帶寬有限等情況下尤為重要。 通常情況下,實(shí)現(xiàn)斷點(diǎn)續(xù)傳需要客戶端和服務(wù)端的相互配合。
以下是一般的實(shí)現(xiàn)步驟:
客戶端發(fā)起文件上傳請(qǐng)求時(shí),向服務(wù)端發(fā)送一個(gè) HTTP 請(qǐng)求,包含文件名、文件大小等信息。
服務(wù)端接收到請(qǐng)求后,根據(jù)文件名和文件大小創(chuàng)建一個(gè)空文件,并返回已經(jīng)上傳的文件大小,如果之前有部分?jǐn)?shù)據(jù)已經(jīng)上傳過(guò),那么服務(wù)端可以根據(jù)已上傳的大小確定從哪個(gè)位置開(kāi)始上傳。
客戶端接收到服務(wù)端返回的已經(jīng)上傳的文件大小后,可以根據(jù)已上傳的大小計(jì)算出下一次應(yīng)該從哪個(gè)位置開(kāi)始上傳。
客戶端將文件切分為多個(gè)小塊,每個(gè)小塊的大小一般為幾十 KB 或幾百 KB,將每個(gè)小塊的數(shù)據(jù)上傳到服務(wù)端,并在每個(gè)小塊的末尾添加一個(gè)分界符,標(biāo)記上傳結(jié)束。
服務(wù)端接收到每個(gè)小塊后,將其存儲(chǔ)到文件對(duì)應(yīng)的位置,等待下一次上傳。
如果上傳過(guò)程中出現(xiàn)中斷,客戶端可以記錄已經(jīng)上傳的文件大小和已經(jīng)上傳的小塊數(shù),下次上傳時(shí)從上一次中斷的位置開(kāi)始繼續(xù)上傳。
總的來(lái)說(shuō),斷點(diǎn)續(xù)傳的實(shí)現(xiàn)需要客戶端和服務(wù)端的相互配合,并需要考慮文件上傳的穩(wěn)定性和可靠性。
2、秒傳怎么實(shí)現(xiàn)?
答:秒傳是指上傳一個(gè)文件時(shí),如果已經(jīng)存在相同的文件,就直接使用已經(jīng)存在的文件,而不需要重新上傳。實(shí)現(xiàn)秒傳需要用到文件的唯一標(biāo)識(shí)。
一種常見(jiàn)的實(shí)現(xiàn)方式是在上傳文件時(shí),先計(jì)算文件的哈希值或者M(jìn)D5值,并將其作為文件的唯一標(biāo)識(shí)。然后將該標(biāo)識(shí)與后臺(tái)數(shù)據(jù)庫(kù)中已經(jīng)存在的文件的標(biāo)識(shí)進(jìn)行比對(duì)。
如果存在相同的標(biāo)識(shí),說(shuō)明該文件已經(jīng)上傳過(guò),那么就直接使用已經(jīng)存在的文件;
如果不存在相同的標(biāo)識(shí),說(shuō)明該文件是一個(gè)新文件,那么就進(jìn)行正常的上傳操作。
在實(shí)現(xiàn)過(guò)程中,可以通過(guò)在前端計(jì)算文件哈希值或MD5值的方式,避免上傳重復(fù)的文件,減少服務(wù)器的壓力,提高文件上傳的效率。
同時(shí),后臺(tái)服務(wù)器也需要維護(hù)一個(gè)文件信息的數(shù)據(jù)庫(kù),用于存儲(chǔ)已經(jīng)上傳過(guò)的文件的唯一標(biāo)識(shí)和存儲(chǔ)路徑等信息,以便實(shí)現(xiàn)秒傳功能。
需要注意的是,文件的唯一標(biāo)識(shí)需要具備唯一性和不可修改性,否則就無(wú)法實(shí)現(xiàn)秒傳功能。
3、var let const 塊級(jí)作用域。
答:在 JavaScript 中,var、let、const 都是聲明變量的關(guān)鍵字,它們?cè)谧饔糜?、賦值和重復(fù)聲明方面有所不同。
var 聲明變量的作用域是函數(shù)級(jí)別的,不受塊級(jí)作用域的限制。在全局作用域中聲明的變量會(huì)成為全局對(duì)象的屬性。
let 聲明的變量是塊級(jí)作用域的,只在聲明的塊內(nèi)有效。在 for 循環(huán)中,每次迭代都會(huì)創(chuàng)建一個(gè)新的變量。
const 聲明的變量也是塊級(jí)作用域的,和 let 類似,但是其值不能被重新賦值,只能被賦值一次。
在開(kāi)發(fā)中,盡可能地使用 let 和 const 來(lái)代替 var,避免變量提升和重復(fù)聲明的問(wèn)題,以及更好地控制變量作用域,提高代碼的可讀性和可維護(hù)性。
4、promise用過(guò)那些api?
答:在 JavaScript 中,Promise 是一種用于處理異步操作的對(duì)象。
它有一些常見(jiàn)的方法可以用來(lái)操作和處理異步操作:
then():指定 Promise 成功(resolve)和失敗(reject)時(shí)的回調(diào)函數(shù),接受兩個(gè)參數(shù),一個(gè)是成功時(shí)的回調(diào)函數(shù),一個(gè)是失敗時(shí)的回調(diào)函數(shù)。
catch():指定 Promise 拒絕(reject)時(shí)的回調(diào)函數(shù),接收一個(gè)參數(shù),即拒絕時(shí)的回調(diào)函數(shù)。
finally():無(wú)論 Promise 成功還是失敗,都會(huì)執(zhí)行的回調(diào)函數(shù),沒(méi)有參數(shù)。
all():接收一個(gè) Promise 數(shù)組,返回一個(gè)新的 Promise,當(dāng)所有 Promise 都成功(resolve)時(shí),返回值為數(shù)組,包含所有 Promise 成功時(shí)的結(jié)果;當(dāng)其中任何一個(gè) Promise 失敗(reject)時(shí),返回值為失敗的 Promise 的值。
race():接收一個(gè) Promise 數(shù)組,返回一個(gè)新的 Promise,當(dāng)其中任何一個(gè) Promise 成功(resolve)或失敗(reject)時(shí),返回值為該 Promise 的值。
除了上述方法外,Promise 還有一些靜態(tài)方法,例如:
Promise.resolve():返回一個(gè)解決(resolve)的 Promise 對(duì)象,可以指定解決的值。
Promise.reject():返回一個(gè)拒絕(reject)的 Promise 對(duì)象,可以指定拒絕的原因。
Promise.allSettled():接收一個(gè) Promise 數(shù)組,返回一個(gè)新的 Promise,當(dāng)所有 Promise 都結(jié)束時(shí),返回值為數(shù)組,包含所有 Promise 的狀態(tài)和值。
Promise.any():接收一個(gè) Promise 數(shù)組,返回一個(gè)新的 Promise,當(dāng)其中任何一個(gè) Promise 成功(resolve)時(shí),返回值為成功的 Promise 的值;當(dāng)所有 Promise 失敗(reject)時(shí),返回值為失敗的 Promise 的值。
以上是 Promise 常見(jiàn)的方法和靜態(tài)方法,可以用來(lái)管理異步操作的狀態(tài)和結(jié)果。
5、Map和Object的區(qū)別。
答:在 JavaScript 中,Map 和 Object 都可以用來(lái)存儲(chǔ)鍵值對(duì)。但是它們之間有幾個(gè)關(guān)鍵的區(qū)別。 鍵的類型:Map 中的鍵可以是任意類型,包括原始類型和對(duì)象引用,而 Object 的鍵必須是字符串或者 Symbol 類型。
插入順序:Map 保留了插入順序,因此在迭代 Map 時(shí)會(huì)按照插入順序返回元素,而 Object 不保留插入順序。
大小:Map 可以使用 size 屬性來(lái)獲取元素的數(shù)量,而 Object 只能手動(dòng)計(jì)算屬性的數(shù)量。
迭代:Map 支持 for-of 循環(huán)和 forEach 方法來(lái)迭代元素,而 Object 只能使用 for-in 循環(huán)來(lái)迭代屬性,但是需要手動(dòng)判斷是否是自身屬性而不是繼承屬性。
性能:在非常大的數(shù)據(jù)集合下,Map 的查找和插入操作通常比 Object 更快。
綜上所述,Map 更適合存儲(chǔ)鍵值對(duì),并需要保留插入順序或使用非字符串類型作為鍵的情況,而 Object 則更適合存儲(chǔ)屬性。
6、vue2和vue3的雙向綁定原理。
答:在vue2中:使用Object.defineProperty對(duì)象以及對(duì)象屬性的劫持+發(fā)布訂閱模式,只要數(shù)據(jù)發(fā)生變化直接通知變化 并驅(qū)動(dòng)視圖更新。
在vue3中的響應(yīng)式采用了ES6中的 Proxy 方法。Proxy 對(duì)象用于定義基本操作的自定義行為(如屬性查找、賦值、枚舉、函數(shù)調(diào)用等)
詳情參考: vue2和vue3的雙向綁定原理_vue2和vue3雙向綁定_m0_73464874的博客-CSDN博客
7、如何封裝組件?
答:封裝組件是前端開(kāi)發(fā)中一個(gè)非常常見(jiàn)的任務(wù),
以下是一些封裝組件的方法:
定義組件API:在設(shè)計(jì)組件時(shí),首先需要考慮它的使用方式。定義組件API有助于其他開(kāi)發(fā)人員快速理解如何使用組件,并確保組件在不同情況下具有一致的行為。
使用props傳遞數(shù)據(jù):在Vue中,組件通過(guò)props屬性接收父組件傳遞的數(shù)據(jù)。在定義組件時(shí),可以指定props屬性的類型、默認(rèn)值和必需性等。
使用slot插槽分發(fā)內(nèi)容:插槽是Vue中一種非常有用的功能,它可以允許組件的使用者插入內(nèi)容到組件中。通過(guò)使用插槽,可以增加組件的靈活性,允許組件的使用者在不同的情況下自由地定制組件的外觀和行為。
使用事件向外通信:組件通常需要與外部環(huán)境進(jìn)行交互。Vue中通過(guò)使用自定義事件可以實(shí)現(xiàn)組件向外部環(huán)境通信的功能。通過(guò)定義事件并在組件中觸發(fā)該事件,可以允許外部環(huán)境對(duì)組件進(jìn)行操作。
使用mixins實(shí)現(xiàn)代碼復(fù)用:Vue中提供了mixins功能,可以將一個(gè)或多個(gè)屬性和方法混合到組件中。通過(guò)使用mixins,可以將常用的功能提取到可重用的模塊中,減少代碼的重復(fù)性。
使用插件擴(kuò)展Vue:Vue插件是一種可以擴(kuò)展Vue功能的機(jī)制。通過(guò)編寫插件,可以為Vue添加全局功能、指令、過(guò)濾器等。使用插件可以提高開(kāi)發(fā)效率,減少代碼量。
使用動(dòng)態(tài)組件:Vue中提供了動(dòng)態(tài)組件的功能。通過(guò)使用動(dòng)態(tài)組件,可以允許組件的使用者在運(yùn)行時(shí)根據(jù)不同的條件選擇不同的組件。
以上是一些封裝組件的方法,當(dāng)然具體的實(shí)現(xiàn)方式還需要根據(jù)具體的業(yè)務(wù)場(chǎng)景和組件功能來(lái)進(jìn)行選擇。
8、實(shí)現(xiàn)棧,有入棧出棧的方法,以及l(fā)ength屬性。
答:棧是一種數(shù)據(jù)結(jié)構(gòu),它是一種線性的、具有一定特殊限制的數(shù)據(jù)結(jié)構(gòu),只能在一端進(jìn)行插入和刪除操作。棧的特點(diǎn)是后進(jìn)先出,即最后壓入的元素最先彈出。

在這個(gè)棧實(shí)現(xiàn)中,我們使用了 push 方法來(lái)進(jìn)行入棧操作,pop 方法來(lái)進(jìn)行出棧操作,peek 方法來(lái)返回棧頂元素,isEmpty 方法來(lái)判斷棧是否為空,length 屬性來(lái)返回棧的長(zhǎng)度。 使用這個(gè)棧實(shí)現(xiàn)的例子:?

針對(duì)以上內(nèi)容,建議大家在已經(jīng)實(shí)戰(zhàn)過(guò)得基礎(chǔ)上,去理解記憶,對(duì)于沒(méi)有實(shí)戰(zhàn)過(guò)的小伙伴,可以先了解。在以后的學(xué)習(xí)中,我們不僅要學(xué)會(huì)在實(shí)戰(zhàn)中運(yùn)用,更要在面試的時(shí)候?qū)⒆约旱闹R(shí)技能流暢的表達(dá)出來(lái),所以面試時(shí)候的語(yǔ)言組織和回答的條理性也是很重要的, 以后我會(huì)經(jīng)常更新一些好的面試題,方便大家學(xué)習(xí)~?
