夏天做啥網(wǎng)站能致富sem優(yōu)化師
自我介紹
您好,面試官!我叫[您的姓名],非常榮幸能有機(jī)會參加這次面試。
在過去的 3 年里,我一直專注于前端開發(fā)領(lǐng)域,積累了豐富的實(shí)踐經(jīng)驗(yàn)。
在 Vue.js 項(xiàng)目中,我能夠熟練運(yùn)用組件化開發(fā)模式,實(shí)現(xiàn)高效的代碼復(fù)用和維護(hù)。對于 React,我也相信我能迅速上手并開發(fā)出功能完善的組件。我對新技術(shù)始終保持著濃厚的興趣和學(xué)習(xí)熱情,不斷探索和嘗試將最新的前端技術(shù)應(yīng)用到實(shí)際項(xiàng)目中。我相信,我的技能和經(jīng)驗(yàn)?zāi)軌驗(yàn)橘F公司的前端項(xiàng)目帶來價值。
前端性能優(yōu)化
前端性能優(yōu)化是提高網(wǎng)站或應(yīng)用程序用戶體驗(yàn)的重要方面,以下是一些常見的前端性能優(yōu)化方法:
1.常見優(yōu)化
-
壓縮Code Minification)和合并文件
壓縮 CSS(MiniCssExtractPlugin+cssnano)、JavaScript(TerserPlugin) 和 HTML 文件,減少文件大小,加快加載速度。
合并多個 CSS 和 JavaScript 文件,減少請求數(shù)量。 -
圖片優(yōu)化(+base 64 asset)
選擇合適的圖片格式(如 JPEG、PNG、WebP 等),根據(jù)圖片內(nèi)容和用途進(jìn)行選擇。
壓縮圖片大小,不影響視覺效果的前提下減少圖片的像素和質(zhì)量。
使用懶加載(Lazy Loading)技術(shù),只在圖片進(jìn)入視口時加載。 -
緩存策略
設(shè)置適當(dāng)?shù)?HTTP 緩存頭,讓瀏覽器緩存靜態(tài)資源,避免重復(fù)請求。
利用 cache (HardSourceWebpackPlugin、persistentCache)選項(xiàng)啟用緩存,提高構(gòu)建速度。為輸出的文件添加 contenthash ,以便瀏覽器有效地利用緩存。
使用 Service Workers 實(shí)現(xiàn)離線緩存和更靈活的緩存控制。 -
代碼優(yōu)化
優(yōu)化 JavaScript 代碼,避免不必要的計(jì)算和循環(huán)。
去除未使用的 CSS 代碼,減少樣式表的大小。 -
減少 HTTP 請求
盡量減少頁面中的圖片、腳本、樣式表等資源的請求數(shù)量。 -
異步加載
對于非關(guān)鍵的 JavaScript 腳本,使用異步加載(如 defer 或 async 屬性),不阻塞頁面渲染。
-
優(yōu)化 CSS 和 JavaScript 的加載順序
將關(guān)鍵的 CSS 放在頁面頭部加載,以避免頁面閃爍。
非關(guān)鍵的 JavaScript 放在頁面底部加載,不影響頁面內(nèi)容的呈現(xiàn)。 -
使用 CDN(內(nèi)容分發(fā)網(wǎng)絡(luò))
利用 CDN 加速靜態(tài)資源的加載,減少網(wǎng)絡(luò)延遲。 -
減少 DOM 操作
避免頻繁的 DOM 讀寫操作,盡量一次性修改 DOM。
2.Webpack優(yōu)化
- 代碼分離(Code Splitting):
利用 splitChunks 插件將代碼分割成多個塊,例如將第三方庫與業(yè)務(wù)代碼分離,或者將不同路由的模塊分離。 - 動態(tài)導(dǎo)入(Dynamic Imports):使用 import() 函數(shù)實(shí)現(xiàn)按需加載模塊。
- css/js代碼壓縮
- cache緩存
- 優(yōu)化模塊解析(Module Resolution Optimization):
合理配置 resolve 選項(xiàng),如設(shè)置 extensions 減少文件擴(kuò)展名的嘗試,指定 modules 減少模塊搜索路徑。
網(wǎng)絡(luò)篇
1. 三次握手,四次揮手。為什么要三次握手,四次揮手,兩次不行嗎?為什么四次揮手比三次握手多一次?
三次握手
三次握手是 TCP 協(xié)議建立連接時使用的一種機(jī)制。
具體過程如下: 第一次握手:客戶端向服務(wù)端發(fā)送一個帶有 SYN標(biāo)志位的數(shù)據(jù)包,表示客戶端想要建立連接,同時初始化序列號(seq)。
第二次握手:服務(wù)端收到客戶端的 SYN 數(shù)據(jù)包后,向客戶端發(fā)送一個帶有SYN 和 ACK 標(biāo)志位的數(shù)據(jù)包,確認(rèn)客戶端的請求,并也初始化自己的序列號(seq),同時確認(rèn)號(ack)為客戶端的序列號加 1。
第三次握手:客戶端收到服務(wù)端的 SYN + ACK 數(shù)據(jù)包后,向服務(wù)端發(fā)送一個帶有 ACK 標(biāo)志位的數(shù)據(jù)包,確認(rèn)號為服務(wù)端的序列號加1,表示客戶端確認(rèn)收到了服務(wù)端的回應(yīng),連接建立成功。
四次揮手
四次揮手是 TCP 協(xié)議斷開連接時使用的機(jī)制。 具體過程如下:
第一次揮手:客戶端向服務(wù)端發(fā)送一個帶有 FIN 標(biāo)志位的數(shù)據(jù)包,表示客戶端沒有數(shù)據(jù)要發(fā)送了,想要關(guān)閉連接。
第二次揮手:服務(wù)端收到客戶端的 FIN 數(shù)據(jù)包后,向客戶端發(fā)送一個帶有 ACK標(biāo)志位的數(shù)據(jù)包,表示服務(wù)端已經(jīng)收到客戶端的關(guān)閉請求。
第三次揮手:服務(wù)端向客戶端發(fā)送一個帶有 FIN標(biāo)志位的數(shù)據(jù)包,表示服務(wù)端也沒有數(shù)據(jù)要發(fā)送了,準(zhǔn)備關(guān)閉連接。
第四次揮手:客戶端收到服務(wù)端的 FIN 數(shù)據(jù)包后,向服務(wù)端發(fā)送一個帶有 ACK 標(biāo)志位的數(shù)據(jù)包,表示客戶端確認(rèn)收到服務(wù)端的關(guān)閉請求,連接完全關(guān)閉。
為什么要三次握手,兩次不行嗎?
三次握手是必要的,兩次握手不行,原因如下:
兩次握手無法確認(rèn)雙方的接收和發(fā)送能力。第一次握手客戶端表明能發(fā)送,但服務(wù)端不知道客戶端能接收。第二次握手服務(wù)端表明能接收和發(fā)送,但客戶端不知道服務(wù)端能接收。
兩次握手可能導(dǎo)致錯誤的連接建立。如果網(wǎng)絡(luò)延遲,舊的請求到達(dá)服務(wù)端,服務(wù)端以為是新的請求而建立連接,會造成資源浪費(fèi)和錯誤。
為什么四次揮手比三次握手多一次?
四次揮手比三次握手多一次,主要是因?yàn)樵?strong>關(guān)閉連接時,雙方的數(shù)據(jù)傳輸狀態(tài)不同。
在三次握手建立連接時,服務(wù)端收到客戶端的連接請求并確認(rèn)后,可以直接將 SYN 和 ACK一起發(fā)送,因?yàn)榇藭r服務(wù)端不需要額外處理未完成的數(shù)據(jù)傳輸。 而在四次揮手關(guān)閉連接時,當(dāng)客戶端發(fā)送 FIN表示沒有數(shù)據(jù)要發(fā)送后,服務(wù)端可能還有數(shù)據(jù)需要繼續(xù)發(fā)送,所以不能立即發(fā)送 FIN 關(guān)閉連接,而是先回復(fù) ACK 確認(rèn)客戶端的關(guān)閉請求。等服務(wù)端數(shù)據(jù)發(fā)送完畢,再發(fā)送 FIN 表示自己也可以關(guān)閉了。因此,關(guān)閉連接時需要多一次交互。
例如,在一個客戶端與服務(wù)端進(jìn)行實(shí)時通信的場景中,客戶端發(fā)送完所有消息并想要關(guān)閉連接(第一次揮手),服務(wù)端收到請求后先回復(fù) ACK
表示知道了(第二次揮手),但此時服務(wù)端可能還有未發(fā)送完的消息,等發(fā)送完后才發(fā)送 FIN 表示自己也準(zhǔn)備關(guān)閉(第三次揮手),客戶端最后回復(fù)
ACK 完成關(guān)閉(第四次揮手)。
2.http,協(xié)議,狀態(tài)碼。http1.0跟 http2.0 的區(qū)別,http跟https的區(qū)別
HTTP 協(xié)議
HTTP(HyperText Transfer Protocol,超文本傳輸協(xié)議)是用于在 Web
上傳輸數(shù)據(jù)的應(yīng)用層協(xié)議。它定義了客戶端和服務(wù)器之間如何進(jìn)行請求和響應(yīng)的交互。
HTTP狀態(tài)碼
200:成功 301:表示請求的資源已被永久移動到新的 URL,客戶端應(yīng)使用新的 URL 訪問
302:表示請求的資源臨時被移動到了其他位置,客戶端應(yīng)繼續(xù)使用原有 URL 進(jìn)行訪問
400、401、403、404:(客戶端)語法出錯、需要認(rèn)證、沒有權(quán)限、找不到 500:(服務(wù)端)出錯
301和302狀態(tài)碼區(qū)別
301 Moved Permanently(永久移動)
含義:表示請求的資源已被永久移動到新的 URL地址。搜索引擎等爬蟲會將鏈接權(quán)重傳遞到新的 URL 。 緩存:瀏覽器和搜索引擎會記住這個重定向,下次訪問相同的請求時會直接訪問新的 URL ,不會再向原 URL 發(fā)送請求。
影響:對 SEO(搜索引擎優(yōu)化)有較大影響,因?yàn)樗阉饕鏁J(rèn)為原 URL 已失效,將權(quán)重轉(zhuǎn)移到新的 URL 。
示例:如果一個網(wǎng)站的域名發(fā)生了永久性的變更,從 olddomain.com 變更為 newdomain.com ,服務(wù)器就會返回 301 狀態(tài)碼,并告知客戶端新的域名地址。
302 Found(臨時移動)
含義:表示請求的資源臨時被移動到了另一個 URL 。
緩存:瀏覽器在接收到 302 響應(yīng)時,不會自動將后續(xù)請求重定向到新的 URL,每次請求都會先訪問原 URL ,由服務(wù)器再次返回 302 重定向到新的地址。
影響:對 SEO 的影響相對較小,搜索引擎不會將原 URL 的權(quán)重立即傳遞給新的 URL ,因?yàn)樗J(rèn)為這只是臨時的重定向。
示例:在網(wǎng)站進(jìn)行臨時維護(hù)或活動期間,將某些頁面臨時重定向到其他頁面時,可能會使用 302 狀態(tài)碼。
例如,假設(shè)一個電商網(wǎng)站進(jìn)行系統(tǒng)升級,預(yù)計(jì)需要幾個小時,在此期間,訪問商品詳情頁可能會被 302 臨時重定向到一個通知頁面。而如果該電商網(wǎng)站決定永久關(guān)閉某個商品分類,并將相關(guān)頁面永久重定向到新的分類頁面,就會使用 301 狀態(tài)碼。
HTTP1和HTTP2的區(qū)別
- 多路復(fù)用:2支持多個請求和響應(yīng)在一個連接上并發(fā)處理1每次都需要建立
- 請求頭壓縮:2頭部信息壓縮,減少傳輸?shù)臄?shù)據(jù)量二進(jìn)制分幀:2將請求和響應(yīng)分割為更小的幀,并進(jìn)行二進(jìn)制編碼傳輸效率
- 服務(wù)器推送:服務(wù)器可以主動向客戶端推送資源,而無需等待客戶端請求。
HTTP和HTTPS的區(qū)別
- 安全:https通過ssl/tls協(xié)議對數(shù)據(jù)進(jìn)行加密,保證了數(shù)據(jù)的機(jī)密性和完整性,防止數(shù)據(jù)盜取和篡改,http使用的是明文傳輸不安全
- 端口:http端口80,https端口443
- 證書:使用https時服務(wù)器需要配置數(shù)字證書來進(jìn)行身份驗(yàn)證,而http則不需要
例如:在線支付場景可以使用https更為嚴(yán)謹(jǐn),而一般的網(wǎng)站http就可以
3.當(dāng)輸入地址后瀏覽器做哪些操作
地址解析—建立tcp連接—發(fā)送http請求—接收服務(wù)器響應(yīng)—處理響應(yīng)—
顯示頁面—后續(xù)交互
-
地址解析
檢查地址格式是否正確
如果使用的是域名,那就去DNC(域名系統(tǒng))服務(wù)器發(fā)送求情,獲取該域名對應(yīng)的Ip地址,如果使用的Ip則直接拿IP簡歷TCP連接 -
建立TCP連接
瀏覽器通過獲取IP地址和端口(http端口80,https端口443)去向服務(wù)段建立tcp連接(3次握手:客SYN-服‘發(fā)送建立請求’服SYN+ACK-客‘確認(rèn)請求’客ACK-服‘收到服務(wù)端確認(rèn),建立連接’) -
發(fā)送HTTP請求
Tcp連接成功后瀏覽器會構(gòu)建http請求報文,里面包括請求方式(post,get)、URL、請求頭(包含各種信息、如接受的內(nèi)容格式)和可能需要的請求體(例post請求需要傳一些請求參數(shù));將這個請求通過已建立的TCP發(fā)送給服務(wù)端 -
接受服務(wù)器響應(yīng)
服務(wù)器接收到請求后,會處理請求并返回一個http響應(yīng)
瀏覽器接收這個響應(yīng),并解析響應(yīng)體和響應(yīng)頭 -
處理響應(yīng)
如果響應(yīng)狀態(tài)為成功(如200),瀏覽器會根據(jù)響應(yīng)頭中的內(nèi)容類型來處理響應(yīng)體 -
顯示頁面
將從服務(wù)器獲取的數(shù)據(jù)放在頁面上并進(jìn)行渲染,最后頁面展示最新的內(nèi)容 -
后續(xù)交互
如果頁面上用其他資源(圖片、css、js),瀏覽器會再次發(fā)送請求獲取該些資源
例如,當(dāng)您輸入一個電商網(wǎng)站的地址,瀏覽器首先解析并獲取服務(wù)器的 IP 地址,建立連接后發(fā)送請求獲取首頁的 HTML 文檔。然后根據(jù)文檔中的資源鏈接繼續(xù)獲取圖片、樣式表和腳本等,逐步構(gòu)建并顯示完整的頁面供您瀏覽和交互。
4.TCP,UDP有什么區(qū)別
TCP(Transmission Control Protocol,傳輸控制協(xié)議)
UDP(User Datagram Protocol,用戶數(shù)據(jù)報協(xié)議)是兩種常見的傳輸層協(xié)議
它們有以下主要區(qū)別:
- 連接性:
TCP是面向連接的協(xié)議,在數(shù)據(jù)傳輸之前需要先建立連接,通過三次握手建立可靠的連接。
UDP是無連接的協(xié)議,不需要事先建立連接,直接發(fā)送數(shù)據(jù) - 可靠性:
TCP提供可靠的數(shù)據(jù)傳輸,通過確認(rèn)。重傳、排序和流量控制機(jī)制,確保數(shù)據(jù)準(zhǔn)確無誤和按序到達(dá)
UDP不保證可靠的交付,可能出現(xiàn)丟包、亂序的情況 - 頭部開銷:
TCP頭部開銷比較大,通常20個字節(jié)
UDP頭部開銷比較小,通常8個字節(jié) - 應(yīng)用場景:
TCP適用于數(shù)據(jù)準(zhǔn)確和可靠行要求較高的應(yīng)用:文件傳輸、電子郵箱、遠(yuǎn)程登陸
UDP適用于對實(shí)時性要求比較高的如視頻會議、直播、在線游戲、實(shí)施音頻
5.Cors請求頭
CORS(跨域資源共享)請求頭是一組 HTTP 頭字段
用于解決瀏覽器的同源策略限制,實(shí)現(xiàn)跨域請求。
當(dāng)一個請求的 URL 的協(xié)議、域名、端口三者之間任意一個與當(dāng)前頁面地址不同時,就會產(chǎn)生跨域問題。為了允許跨域請求,服務(wù)器需要在響應(yīng)中添加特定的 CORS請求頭,告訴瀏覽器該請求可以跨域訪問資源。
為了允許跨域請求,服務(wù)器需要在響應(yīng)中添加特定的 CORS 請求頭,告訴瀏覽器該請求可以跨域訪問資源。
常見的 CORS 請求頭包括:
Access-Control-Allow-Origin:指定允許訪問該資源的源(Origin),可以是具體的域名(如http://example.com)或通配符*(表示允許任何源訪問)。
Access-Control-Allow-Methods:指定允許的跨域請求方法,如GET、POST、PUT、DELETE等,多個方法之間用逗號分隔。
Access-Control-Allow-Headers:指定允許的跨域請求頭字段,多個字段之間用逗號分隔。
Access-Control-Expose-Headers:指定客戶端可以訪問的額外響應(yīng)頭字段。
Access-Control-Max-Age:指定預(yù)檢請求(Preflight request)的結(jié)果可以被緩存的時間(以秒為單位),在緩存有效期內(nèi),瀏覽器無需再次發(fā)送預(yù)檢請求。
Access-Control-Allow-Credentials:當(dāng)需要跨域發(fā)送 Cookie 或其他憑證信息時,將該字段設(shè)置為true。但需注意,如果設(shè)置了該字段為true,Access-Control-Allow-Origin不能設(shè)置為通配符*,而必須指定具體的域名。
6.Get,POST請求
- 數(shù)據(jù)傳遞
Get:掛在瀏覽器的地址欄上面
Post:將數(shù)據(jù)放在請求體中進(jìn)行傳遞 - 數(shù)據(jù)長度受限
Get:受到url長度限制,不適合傳大量的數(shù)據(jù)
Post:不受限制,可以傳輸大量數(shù)據(jù) - 安全性
Get安全性差url上不適合傳敏感信息post數(shù)據(jù)在請求體內(nèi)相對更安全 - 用途
Get:常用于獲取數(shù)據(jù),如查詢操作
Post:常用于提交數(shù)據(jù),表單或上傳文件等
7.CSRF,XSS攻擊
CSRF(Cross-Site Request Forgery,跨站請求偽造)和
XSS(Cross-Site Scripting,跨站腳本攻擊)是兩種常見的 Web 安全攻擊方式。
CSRF 攻擊是指攻擊者誘導(dǎo)受害者在已經(jīng)登錄的 Web 應(yīng)用程序中執(zhí)行他們事先精心構(gòu)造的惡意請求。例如,攻擊者可能構(gòu)造一個惡意的鏈接或表單,當(dāng)受害者在登錄狀態(tài)下點(diǎn)擊或提交時,會在受害者不知情的情況下執(zhí)行一些危險操作,如修改密碼、轉(zhuǎn)賬等。
XSS 攻擊則是指攻擊者通過在目標(biāo)網(wǎng)站注入惡意腳本代碼,當(dāng)其他用戶訪問該網(wǎng)站時,惡意腳本會在用戶瀏覽器中執(zhí)行,從而獲取用戶的敏感信息(如 Cookie、會話令牌等)、篡改頁面內(nèi)容或進(jìn)行其他惡意操作。
為了防范這兩種攻擊,可以采取多種措施:
如驗(yàn)證請求來源、設(shè)置 CSRF 令牌、對用戶輸入進(jìn)行嚴(yán)格的過濾和轉(zhuǎn)義、設(shè)置 HttpOnly 屬性防止 Cookie 被腳本獲取等。
8.HTTP緩存
HTTP 緩存是一種用于提高 Web 應(yīng)用性能和減少網(wǎng)絡(luò)帶寬使用的機(jī)制。
-
強(qiáng)緩存
通過 Expires 和 Cache-Control 響應(yīng)頭來控制。
Expires 指明資源的過期時間。
Cache-Control 可以設(shè)置更精確的緩存策略,如 max-age 表示資源在多少秒內(nèi)有效。<meta http-equiv="Cache-Control" content="max-age=31536000" /><metahttp-equiv="Expires"content="Thu, 31 Dec 2030 23:59:59 GMT" />
當(dāng)緩存未過期時,瀏覽器直接從本地緩存獲取資源,不會向服務(wù)器發(fā)送請求。
-
協(xié)商緩存
服務(wù)器通過 Last-Modified 告知瀏覽器資源的最后修改時間,瀏覽器再次請求時通過 If-Modified-Since 帶上這個時間,服務(wù)器對比判斷資源是否有更新,如果沒有則返回 304 狀態(tài)碼,告知瀏覽器使用本地緩存。ETag 是服務(wù)器為資源生成的唯一標(biāo)識,瀏覽器下次請求通過 If-None-Match 帶上這個標(biāo)識,服務(wù)器對比判斷,決定是否返回新的資源。
在前端頁面中設(shè)置(通過 HTML 的 標(biāo)簽)例如,一個網(wǎng)站的圖片設(shè)置了強(qiáng)緩存,有效期為 1 天。當(dāng)用戶在一天內(nèi)再次訪問該頁面時,瀏覽器直接從緩存中讀取圖片,無需再次從服務(wù)器下載,大大提高了頁面加載速度。
又比如,對于經(jīng)常更新的網(wǎng)頁內(nèi)容,服務(wù)器可以使用協(xié)商緩存,根據(jù)資源的實(shí)際修改情況決定是否讓瀏覽器使用緩存。
9.Options預(yù)檢請求
在 HTTP 協(xié)議中,“OPTIONS”是一種請求方法。當(dāng)客戶端向服務(wù)器發(fā)送 OPTIONS 請求時,它通常用于獲取服務(wù)器支持的 HTTP 方法和其他與請求/響應(yīng)相關(guān)的選項(xiàng)信息。
例如,在進(jìn)行跨域請求之前,瀏覽器可能會先發(fā)送 OPTIONS 請求來檢查服務(wù)器是否允許特定的跨域請求方法和頭信息。
JS篇
0-1. 數(shù)組方法
改變原數(shù)組:push、pop、shift、unshift、sort、splice、reverse
不改變原屬組:concat、join、map、forEach、filter、slice
0-2. 高階函數(shù)
高階函數(shù)是至少滿足下列一個條件的函數(shù):?接受一個或多個函數(shù)作為輸入,?或輸出一個函數(shù)。?
Array擴(kuò)展:
forEach、map、reduce、filter、sort 、every 、some 、find 、findIndex
let arr = [68, 53, 12];
// forEach里面?zhèn)鞯氖呛瘮?shù)(滿足一個)
arr.forEach((item, index) => {console.log(`第${index}個數(shù)是:${item}`);
})
// forEach里面?zhèn)鞯氖呛瘮?shù)并且也有返回值(滿足兩個個)
const map = arr.map(function(i){return i*i
});
0-3 script 中async和defer表示什么意思
async 和 defer 是兩個屬性,用于控制腳本的加載和執(zhí)行方式
當(dāng) script標(biāo)簽設(shè)置了 async 屬性時,腳本將異步加載,并且一旦下載完成,就會立即執(zhí)行,不會阻塞頁面的渲染。這意味著腳本的執(zhí)行順序是不確定的,可能會在頁面的其他部分還在加載和渲染時就開始執(zhí)行。
當(dāng) script 標(biāo)簽設(shè)置了 defer 屬性時,腳本會異步加載,但會等到頁面的解析(DOM 構(gòu)建)完成后,按照它們在頁面中出現(xiàn)的順序依次執(zhí)行。這意味著腳本不會阻塞頁面的初始渲染,但執(zhí)行順序是有保證的。
0-4 Dom事件流的順序?什么是事件委托?
當(dāng)頁面上的一個元素被點(diǎn)擊時,先從document向下一層層捕獲到該元素。然后再向上冒泡,一層層觸發(fā)。
事件委托是將事件寫在父級元素上,e.target是事件捕獲時那個最小的元素,即選中的元素。所以可以根據(jù)e.target操作選中的元素。這樣不需要給每個子元素綁定事件,代碼更加簡約。
0-5. break/continue/return的使用場景?
break:用于結(jié)束整個循環(huán)(for、while、do-while)
continue:用于結(jié)束循環(huán)中的當(dāng)前層循環(huán),進(jìn)入下一層循環(huán)
return:用戶結(jié)束整個函數(shù)
0-. 閉包是什么?利弊?如何解決弊端?使用場景?
場景:
事件處理、回調(diào)函數(shù)、遞歸、鏈?zhǔn)秸{(diào)用
閉包是什么:
JS中內(nèi)層函數(shù)可以訪問外層函數(shù)的變量,外層函數(shù)無法操作內(nèi)存函數(shù)的變量的特性。我們把這個特性稱作閉包。
閉包的好處:
- 隔離作用域,保護(hù)私有變量;有了閉包才有局部變量,要不然都是全局變量了。
- 讓我們可以使用回調(diào),操作其他函數(shù)內(nèi)部;
- 變量長期駐扎在內(nèi)存中,不會被內(nèi)存回收機(jī)制回收,即延長變量的生命周期;
閉包的弊端:
內(nèi)層函數(shù)引用外層函數(shù)變量,內(nèi)層函數(shù)占用內(nèi)存。如果不釋放內(nèi)存,過多時,易引起內(nèi)存泄露。
解決辦法:無法自動銷戶,就及時手動回收,使用后將函數(shù)的引用賦null。
1.事件循環(huán)機(jī)制(event loop)
事件循環(huán)(Event Loop)是 JavaScript 運(yùn)行時環(huán)境用于處理異步操作的一種機(jī)制。
在 JavaScript 中,同步任務(wù)會在調(diào)用棧中依次執(zhí)行,而異步任務(wù)會在合適的時機(jī)被放入任務(wù)隊(duì)列中等待執(zhí)行。
事件循環(huán)的主要工作流程如下:
- 首先,執(zhí)行同步任務(wù),這些任務(wù)會依次進(jìn)入調(diào)用棧并執(zhí)行,直到調(diào)用棧為空。
- 然后,事件循環(huán)會檢查任務(wù)隊(duì)列(通常包括宏任務(wù)隊(duì)列和微任務(wù)隊(duì)列)。
宏任務(wù)(MacroTask),例如 setTimeout 、 setInterval 、 IO 操作等,會被放入宏任務(wù)隊(duì)列。
微任務(wù)(MicroTask),如 Promise.then 、 MutationObserver 等,會被放入微任務(wù)隊(duì)列。
- 事件循環(huán)會先處理微任務(wù)隊(duì)列中的所有任務(wù),直到微任務(wù)隊(duì)列為空。
- 接著,從宏任務(wù)隊(duì)列中取出一個任務(wù)并執(zhí)行。
- 執(zhí)行完一個宏任務(wù)后,再次檢查微任務(wù)隊(duì)列,重復(fù)上述過程。
通過這種機(jī)制,JavaScript 能夠在單線程環(huán)境中有效地處理異步操作,不會造成阻塞,從而保證了程序的響應(yīng)性和性能。
2.Null跟underfine的區(qū)別
Null 和 Undefined 在 JavaScript 中有以下區(qū)別:
- 含義:
Null 表示一個被明確賦值為空的對象引用。
Undefined 表示一個變量未被初始化或者一個對象中不存在的屬性。 - 類型:
typeof null 的結(jié)果是 “object” ,這是 JavaScript 中的一個歷史遺留問題。
typeof undefined 的結(jié)果是 “undefined” 。
3.Promise
Promise 是 JavaScript 中處理異步操作的一種機(jī)制。
創(chuàng)建一個 Promise 對象通常需要傳入一個執(zhí)行器函數(shù),該函數(shù)接受兩個參數(shù) resolve 和 reject ,用于改變 Promise 的狀態(tài)
它具有以下特點(diǎn)和優(yōu)勢:
- 解決回調(diào)地獄:通過鏈?zhǔn)秸{(diào)用 then 方法,可以更清晰地組織異步操作的邏輯,避免多層嵌套的回調(diào)函數(shù)導(dǎo)致的代碼可讀性差和維護(hù)困難的問題。
- 明確的狀態(tài):Promise 有三種狀態(tài):pending(等待)、fulfilled(成功)和 rejected(失敗)。一旦狀態(tài)確定,就不可再改變。
- 錯誤處理:可以使用 catch 方法統(tǒng)一處理異步操作中的錯誤。
Promise.all([promise1,promise2]).then(res=>{}).catch(err=>{})
4.判斷一個屬性是對象還是數(shù)組
Array.isArray()+typeOf
5.New操作符做了哪些操作
- 創(chuàng)建一個新的空對象:這個對象將成為構(gòu)造函數(shù)創(chuàng)建的實(shí)例。
- 將新創(chuàng)建的對象的 __ proto__ 屬性指向構(gòu)造函數(shù)的 prototype 對象,從而建立實(shí)例與構(gòu)造函數(shù)原型之間的鏈接,實(shí)現(xiàn)了繼承和方法共享。
- 將構(gòu)造函數(shù)中的 this 綁定到新創(chuàng)建的對象上。
- 執(zhí)行構(gòu)造函數(shù)中的代碼:這可能包括屬性的初始化、方法的定義等操作。
如果構(gòu)造函數(shù)有返回值,并且返回值是一個對象類型(不是原始類型),則返回這個對象,否則返回新創(chuàng)建的對象。
6.Node非阻塞i/o
非阻塞 I/O 意味著當(dāng) Node.js 發(fā)起一個 I/O操作(如文件讀取、網(wǎng)絡(luò)請求等)時,不會阻塞當(dāng)前線程等待操作完成,而是繼續(xù)執(zhí)行后續(xù)的代碼。當(dāng) I/O操作完成時,通過回調(diào)函數(shù)或事件通知來處理結(jié)果。提高高并發(fā)處理能力和充分利用系統(tǒng)資源(Web 服務(wù)器、實(shí)時聊天、文件上傳下載)
缺點(diǎn):編程復(fù)雜增加開銷(多了回調(diào)函數(shù))、錯誤內(nèi)容處理棘手
7.commonJS跟requireJS和ES6的區(qū)別
- 加載方式:
CommonJS 是同步加載,代碼執(zhí)行到 require 語句時會阻塞等待模塊加載完成。
RequireJS 是異步加載,不會阻塞后續(xù)代碼的執(zhí)行。
ES6 模塊在編譯時確定模塊的依賴關(guān)系,在運(yùn)行時異步加載。 - 模塊導(dǎo)出:
CommonJS 主要通過 module.exports 或 exports 來導(dǎo)出。
RequireJS 中模塊通過定義函數(shù)并返回一個對象來導(dǎo)出。
ES6 模塊可以使用 export default 導(dǎo)出默認(rèn)值,或者使用 export 關(guān)鍵字導(dǎo)出多個具名的變量、函數(shù)、類等。 - 模塊導(dǎo)入:
CommonJS 使用 require 函數(shù)引入模塊,返回的是模塊導(dǎo)出的對象的副本。
RequireJS 使用 require 函數(shù),通過配置模塊的路徑和依賴來加載。
ES6 模塊使用 import 語句導(dǎo)入,導(dǎo)入的是只讀的綁定,而非值的副本。 - 運(yùn)行環(huán)境:
CommonJS 常用于服務(wù)器端,如 Node.js 。
RequireJS 主要用于瀏覽器端。
ES6 模塊既可以用于服務(wù)器端,也可以用于現(xiàn)代瀏覽器端。 - 模塊循環(huán)引用:
CommonJS 可以較好地處理模塊的循環(huán)引用。
RequireJS 也能處理循環(huán)引用,但方式與 CommonJS 不同。
ES6 模塊在編譯階段確定依賴,原則上不支持循環(huán)引用,如果存在會報錯。
8.基本數(shù)據(jù)類型
Number/string/boolen/null/indefind/symbol
i基礎(chǔ)數(shù)據(jù)類型修改對應(yīng)的棧就重新生成
9.es6語法,箭頭函數(shù),新的操作方法等
模板字符串、結(jié)構(gòu)、set、map、箭頭函數(shù)、默認(rèn)參數(shù)、for of、擴(kuò)展運(yùn)算、promise、es6model
10.dom0跟dom2結(jié)構(gòu)
DOM0 和 DOM2 是文檔對象模型的不同級別,它們在處理事件的方式上有所不同。
DOM0 點(diǎn)擊事件
DOM2 可以監(jiān)聽點(diǎn)擊事件并捕獲各種階段(捕獲、目標(biāo)、冒泡)
DOM2 級的事件處理方式相比 DOM0 級更加規(guī)范和靈活,能夠更好地管理多個事件處理程序,并且支持事件的捕獲和冒泡階段。
11.bind跟apply,call的區(qū)別,實(shí)現(xiàn)方式
getting.call(obj,”vlaue1”)
getting.apply(obj,[”vlaue1”,”vlaue2”])
call、apply上面兩個會立即執(zhí)行函數(shù)
而const newFun = getting.bind(obj,”vlaue1”);
newFun ()是創(chuàng)建一個新的函數(shù)并改變其 this 指向和預(yù)設(shè)部分參數(shù),新函數(shù)需要手動調(diào)用執(zhí)行。
12.深拷貝,淺拷貝
淺拷貝(Object.assign()、擴(kuò)展運(yùn)算符)
淺拷貝創(chuàng)建一個新的對象或數(shù)組,但它只復(fù)制原始對象或數(shù)組的頂層屬性或元素。如果原始對象或數(shù)組的屬性值是引用類型(如對象或數(shù)組),則淺拷貝會復(fù)制引用而不是創(chuàng)建新的引用類型實(shí)例。
深拷貝(JSON.parse(JSON.stringify())、clonedeep)
深拷貝會遞歸地復(fù)制原始對象或數(shù)組的所有屬性和子屬性,創(chuàng)建完全獨(dú)立的副本,原始對象的修改不會影響到深拷貝的結(jié)果。
14.跨域,同源策略
所謂“同源”,指的是兩個 URL 的協(xié)議、域名和端口都相同。
同源策略主要限制了以下幾種操作:
Cookie、LocalStorage 和 IndexedDB 等數(shù)據(jù)無法跨域讀取。
DOM 無法跨域操作。
AJAX 請求無法跨域發(fā)送(除非服務(wù)器明確允許)。
跨域:當(dāng)瀏覽器請求的資源與當(dāng)前頁面的源不同時,就產(chǎn)生了跨域請求。
常見的跨域解決方案有:
- JSONP:利用 script標(biāo)簽的跨域能力,通過動態(tài)創(chuàng)建 script 標(biāo)簽并指定回調(diào)函數(shù)來獲取數(shù)據(jù)。
- CORS:服務(wù)器端設(shè)置響應(yīng)頭,允許特定源的請求訪問。
- nignx代理:在同域的服務(wù)器端轉(zhuǎn)發(fā)跨域請求,將獲取到的數(shù)據(jù)返回給前端。
15.快速排序
快速排序(Quick Sort)是一種分治的排序算法。它的平均時間復(fù)雜度為O(nlogn) ,空間復(fù)雜度為O(logn),最壞時間復(fù)雜度為O(n方)
以下是快速排序的基本步驟:
- 選擇一個基準(zhǔn)元素(pivot),通??梢赃x擇數(shù)組的第一個元素、最后一個元素或中間元素。
- 對數(shù)組進(jìn)行分區(qū)(partition)操作:將小于基準(zhǔn)的元素放在基準(zhǔn)的左邊,大于基準(zhǔn)的元素放在基準(zhǔn)的右邊。分區(qū)操作完成后,基準(zhǔn)元素處于最終排序后的正確位置。
- 對基準(zhǔn)元素左邊和右邊的子數(shù)組分別遞歸地重復(fù)步驟 1 和 2,直到整個數(shù)組有序。
16.解釋原型繼承如何工作
每個函數(shù)都有一個 prototype 屬性,當(dāng)使用這個函數(shù)作為構(gòu)造函數(shù)創(chuàng)建對象實(shí)例時,這些實(shí)例可以通過 __proto__指針訪問構(gòu)造函數(shù)的prototype 對象。當(dāng)試圖訪問實(shí)例對象的某個屬性或方法時,如果在本身找不到,JS引擎會沿著 __proto__鏈向上(原型對象)查找,如果在整個原型鏈中都沒有找到該屬性或方法,最終會返回undefined。這種機(jī)制可以讓多個實(shí)例共享來自原型對象的方法和屬性,可以在保持代碼復(fù)用和靈活性的同時,實(shí)現(xiàn)對象之間的層次結(jié)構(gòu)和功能共享。
17.解釋 JavaScript 中“this”的工作原理
- 普通函數(shù)調(diào)用:在非嚴(yán)格模式下,this指向全局對象(在瀏覽器中為window,在 Node.js 中為global);在嚴(yán)格模式下,this會綁定到undefined。
- 對象方法調(diào)用:this指向調(diào)用該方法的對象。
- 構(gòu)造函數(shù)調(diào)用:使用new關(guān)鍵字調(diào)用構(gòu)造函數(shù)時,this指的是實(shí)例化的新對象。
- apply和call調(diào)用:通過這兩個方法顯式地指定this所指向的對象,即this指向參數(shù)中的對象。
- 箭頭函數(shù):箭頭函數(shù)沒有自己的this,而是繼承外層函數(shù)的this。
- 定時器中調(diào)用:例如setInterval和setTimeout,this指向的是全局變量(在瀏覽器中為window)。
18、New Set()的用法
類似數(shù)組、成員唯一用于數(shù)組去重
add()
clear()
delete()
has()
forEach()
[…new set(arr)]
19、描述一下 async、await 的用法及使用場景
ayayn/await主要用于異步操作,將異步代碼從視覺上看來比較同步化更加簡潔易讀。
用法
1. ayayn 將一個函數(shù)標(biāo)示為一個異步函數(shù),在異步函數(shù)中可以使用await等待異步操作
2. await 只能在async中使用,等待異步函數(shù)的操作完成,獲取異步函數(shù)執(zhí)行的結(jié)果
使用場景
1. 網(wǎng)絡(luò)請求 (獲取頁面渲染的數(shù)據(jù))
2. 數(shù)據(jù)庫操作(等待查詢或更新)
20、for in 與 for of
for-in 遍歷對象 key 為對象的 key,遍歷數(shù)組的話 key 為索引數(shù);for-of 用來遍歷數(shù)組,不能遍歷普通對象
HTML,CSS篇
重繪和重排(回流/重構(gòu)/重載)是什么?如何優(yōu)化?
樣式的調(diào)整會引起重繪,比如字體顏色、背景色調(diào)整等
Dom的變動會引起重排,比如定位改動、元素寬高調(diào)整
偽類和偽元素區(qū)別?
偽類本質(zhì)上用于彌補(bǔ)常規(guī)css選擇器的不足,因?yàn)槿绻麤]有我們可能需要多寫一個class,所以叫偽類
.class:last-child{}
.class:first-child{}a:link {color:green;}
a:visited {color:green;}
a:hover {color:red;}
a:active {color:yellow;}
偽元素本質(zhì)上是創(chuàng)建了一個有內(nèi)容的虛擬元素,如::before ::after。因?yàn)橄喈?dāng)于多了一個元素/節(jié)點(diǎn),所以叫為元素
// :before用于在某個元素之前插入某些內(nèi)容。
// :after用于在某個元素之后插入某些內(nèi)容。
css
p:before{content:"Read this: ";
}html:
<p>I live in Ducksburg</p>頁面展示:
Read this: I live in DucksburgF12看dom中:
before
Read this: I live in Ducksburg
1.h5新增屬性
本地存儲,比如localStorage、sessionStorage
語義化標(biāo)簽,如header、footer、nav等,使代碼結(jié)構(gòu)清晰,利于seo
canvas
svg
web worker,在主線程外再創(chuàng)建一個線程,可與主線程交互
拖放功能
2.Css3新增屬性,常問flex,transform
transform: translate(50px, 50px) rotate(30deg) scale(1.5);
3.本地存儲
- cookie:
常用于保存用戶登錄狀態(tài),每次請求都會攜帶(4k) - localStorage:
存儲數(shù)據(jù)量比較大的數(shù)據(jù),只要瀏覽器不清除就一直會在(5m) - sessionStorage:
用于同一會話區(qū)間保存臨時數(shù)據(jù),比如表單數(shù)據(jù)等,窗口關(guān)閉數(shù)據(jù)清空(5m)
4.Meta有哪些屬性
標(biāo)簽位于文檔的 部分;一個 標(biāo)簽只能用于一種用途,如果想要使用多種特性,需要添加多個 標(biāo)簽;
charset=“utf-8” 字符編譯
viewport 用于設(shè)置視口
http-equiv 網(wǎng)絡(luò)緩存
content-security-policy 防止跨站點(diǎn)腳本攻擊
5.怎么實(shí)現(xiàn)移動端適配
- 使用 viewport 元標(biāo)簽
<meta
name="viewport"
content="width-device-width,
initial-scale=1.0, maximum-scale=1.0,
user-scalable=no">
width=device-width 視口寬度與設(shè)備寬度一致,不設(shè)置的話瀏覽器會默認(rèn)給個較寬值可能在移動端就不友好
- 媒體查詢(Media Queries)@Media screen
- 彈性布局(Flexbox)和網(wǎng)格布局(Grid)
- 相對單位(rem相對根元素、vh/vw相對視口)
- 圖片適配 banckground-size:cover
6.水平垂直居中方式
框架篇
vue
0. v2/v3/v3.2 v-model實(shí)現(xiàn)方法
v2 通過 value和input(‘update:value’, $event")事件
v3 通過 modleValue和input(‘update:modelValue’, $event")
v3.2通過 @update:title=“value= $event”
1.Vue數(shù)據(jù)雙向綁定原理
- vue2 原理是使用 es5 的 api:object.defineProperty()對數(shù)據(jù)進(jìn)行劫持結(jié)合發(fā)布訂閱模式的方式來實(shí)現(xiàn)。
- vue3 使用的是 es6 的 proxy 實(shí)現(xiàn)的,Proxy 用于創(chuàng)建一個數(shù)據(jù)代理,當(dāng)屬性被訪問或修改時,觸發(fā) Proxy 攔截器,實(shí)現(xiàn)數(shù)據(jù)響應(yīng)式。
在 Vue 2 中,雙向數(shù)據(jù)綁定是利用 ES5 的一個
API,Object.defineProperty()對數(shù)據(jù)進(jìn)行劫持結(jié)合發(fā)布訂閱模式的方式來實(shí)現(xiàn)的。通過Object.defineProperty()來劫持?jǐn)?shù)據(jù)對象的屬性,對屬性getter和setter進(jìn)行攔截,當(dāng)屬性被訪問或修改時,除非getter和setter,否則實(shí)現(xiàn)數(shù)據(jù)響應(yīng)式。每個數(shù)據(jù)都有一個Watcher實(shí)例,當(dāng)數(shù)據(jù)發(fā)生變化時,觸發(fā)setter,并通知Watcher,然后Watcher會調(diào)用其函數(shù),將值更新在DOM。
而 Vue 3 中的雙向數(shù)據(jù)綁定則是基于 ES6 的Proxy實(shí)現(xiàn)的。Proxy用于創(chuàng)建一個數(shù)據(jù)代理,當(dāng)屬性被訪問或修改時,觸發(fā)Proxy攔截器,實(shí)現(xiàn)數(shù)據(jù)響應(yīng)式。Proxy相較于Object.defineProperty()的優(yōu)勢在于它可以直接監(jiān)聽對象而非屬性,直接監(jiān)聽數(shù)組的變化,并且攔截方式較多。Proxy返回一個新對象,可以只操作新對象達(dá)到目的,而Object.defineProperty()只能遍歷對象屬性直接修改。
2.路由實(shí)現(xiàn)原理
路由管理器,它的實(shí)現(xiàn)原理主要是通過改變?yōu)g覽器的 URL 來實(shí)現(xiàn)不同頁面(組件)的切換,同時在不重新請求頁面的情況下更新視圖。
在瀏覽器環(huán)境下,Vue Router 主要有兩種實(shí)現(xiàn)模式:hash 模式和 history 模式。
- hash 模式:
URL 中帶有#,#后面的內(nèi)容作為路徑地址使用。
hash 模式的實(shí)現(xiàn)是基于錨點(diǎn)和onhashchange事件。hash 雖然出現(xiàn)在 URL 中,但不會被包括在 HTTP 請求中,它是用來指導(dǎo)瀏覽器動作的,對服務(wù)器端完全無用,改變 hash 不會重新加載頁面,不會出現(xiàn)404。
每一次改變 hash(window.location.hash),都會在瀏覽器的訪問歷史中增加一個記錄。 - history 模式:
通過 HTML5 的history.pushState()和history.replaceState()方法改變地址欄,只改變了地址欄,并不會真正跳轉(zhuǎn)到真正的路徑。
需監(jiān)聽popstate事件,當(dāng)點(diǎn)擊瀏覽器前進(jìn)后退按鈕,或者通過 JavaScript 觸發(fā)back或者forward時才會觸發(fā)。
需要服務(wù)器端進(jìn)行相應(yīng)配置以處理頁面刷新時的 404 錯誤。
這種模式充分利用了 HTML5 History Interface 中新增的方法,使 URL 看起來更美觀、更接近真實(shí)的路徑,但需要服務(wù)器的支持。因?yàn)闆]有#號,當(dāng)用戶刷新頁面之類的操作時,瀏覽器會給服務(wù)器發(fā)送請求,為避免出現(xiàn)這種情況,需要服務(wù)器將除了靜態(tài)資源外所有路由都重定向到根頁面。
傳參
router 包含所有路由信息和方法
route 只包含當(dāng)前路由信息<router-link :to="{ name:'router1',params: { id: status ,id2:status3},query: { queryId: status2 }}" >router-link跳轉(zhuǎn)router1</router-link>```
區(qū)別:
URL 表現(xiàn)形式:
param:參數(shù)作為 URL 路徑的一部分。 有**/**標(biāo)志 this.$route.params
query:參數(shù)以 ?key=value 的形式附加在 URL 后面。有?標(biāo)志 this.$route.query
刷新頁面影響: param:頁面刷新不會丟失參數(shù)。 query:頁面刷新參數(shù)仍然存在。
3.Watch跟computed的區(qū)別
- computed(計(jì)算屬性)
- 多對一 通過現(xiàn)有的數(shù)據(jù)計(jì)算出一個新的值,具有緩存性(當(dāng)依賴變化會重新計(jì)算)
- watch(監(jiān)聽屬性)
1. 一對多 監(jiān)聽某一個特定屬性(對象的單個屬性或整個對象)執(zhí)行相應(yīng)的回調(diào)函數(shù),沒有緩存,每次變化都會觸發(fā)
- 區(qū)別就是computed側(cè)重于數(shù)據(jù)派發(fā);watch側(cè)重于數(shù)據(jù)變化后對復(fù)雜邏輯的處理操作
4.Watch的配置項(xiàng)
Immdera 立即執(zhí)行
Deep
5.為什么數(shù)組push,vue能跟蹤到數(shù)據(jù)發(fā)生變化,用下標(biāo)方式不行
Vue 使用 Object.defineProperty 把數(shù)據(jù)對象的屬性轉(zhuǎn)為 getter/setter,從而實(shí)現(xiàn)對數(shù)據(jù)變化的監(jiān)聽。然而,對于數(shù)組,Vue 不能檢測通過索引直接設(shè)置數(shù)組項(xiàng)和修改數(shù)組長度這兩種變動。
當(dāng)使用 push 等方法時,這些方法是 Vue 經(jīng)過特殊處理的,它們會觸發(fā) Vue 的更新機(jī)制,從而通知視圖進(jìn)行更新。例如 push 方法向數(shù)組末尾添加元素,會改變數(shù)組的內(nèi)容,并且 Vue 能夠感知到這種變化。
6.怎么實(shí)現(xiàn)一個組件的封裝
創(chuàng)建 — 引入 — 注冊 — 使用
v-model的原理 (v-model其實(shí)是個語法糖)
在 Vue 中,v-model 是一個用于實(shí)現(xiàn)表單元素和組件數(shù)據(jù)雙向綁定的指令。 其原理主要包括以下幾個方面: 對于原生的表單元素(如 input、textarea、select 等): v-model 實(shí)際上是 value 屬性和 input 事件的語法糖。
當(dāng)用戶輸入內(nèi)容時,會觸發(fā)元素的 input 事件,Vue 會通過這個事件來更新組件實(shí)例中的數(shù)據(jù)。
同時,組件實(shí)例中的數(shù)據(jù)變化也會同步更新到元素的 value 屬性上,從而實(shí)現(xiàn)雙向綁定。
對于自定義組件: 父組件使用 v-model時,子組件需要接收一個名為 value 的 prop,并觸發(fā)一個名為 input 的自定義事件來更新父組件傳遞的值。
7.MVVM模式的核心
通過數(shù)據(jù)綁定和 ViewModel 實(shí)現(xiàn)視圖和模型的高效交互和低耦合,從而提高應(yīng)用程序的開發(fā)效率和可維護(hù)性。
8.Provider跟inject
Provider 和 inject 是 Vue 中用于實(shí)現(xiàn)依賴注入的兩個概念。它們的主要作用是允許祖先組件向其所有子孫后代組件傳遞數(shù)據(jù)或方法,而不論組件之間的嵌套層次有多深。
在 Vue 2 和 Vue 3 中都可以使用 provide 和 inject,但具體的使用方式略有不同。
9.Keep-alive及其生命周期
activated:在組件被激活時調(diào)用
deactivated:在組件被停用時調(diào)用
需要注意的是,使用 keep-alive 后,原本的 beforeDestroy 和 destroyed 鉤子函數(shù)將不會再被觸發(fā),因?yàn)榻M件不會被真正銷毀,只是被緩存起來了。
另外,keep-alive 組件還支持通過 include、exclude 屬性或動態(tài)判斷來有條件地緩存組件。
keep-alive 常用于需要頻繁切換但又希望保持狀態(tài)的組件,比如列表頁、詳情頁等,以減少服務(wù)器請求次數(shù)和提高用戶體驗(yàn)
10.不想讓vue中data里的一個對象里所以屬性都具有setter,getter,怎么解決?(freeze)
Object.freeze()
11.Slot
- 匿名插槽 (默認(rèn)插槽)
子組件中沒有指定名稱的slot標(biāo)簽
父組件傳遞的未具名內(nèi)容會填充到默認(rèn)插槽中 - 具名
子組件中使用 name 屬性為插槽命名。
父組件使用 template 標(biāo)簽并通過 v-slot:插槽名 來傳遞對應(yīng)名稱的內(nèi)容。
// 子組件
<slot name="header">默認(rèn)的頭部內(nèi)容</slot>
// 父組件
<template v-slot:header><p>父組件傳遞的頭部內(nèi)容</p>
</template>
- 作用域
子組件向插槽傳遞數(shù)據(jù)。
父組件通過接收這些數(shù)據(jù)來決定如何渲染插槽內(nèi)容
// 子組件<slot :user="user"><p>默認(rèn)用戶信息:未知</p></slot>data() {return {user: { name: '張三', age: 25 }};}
// 父組件
<template v-slot="{ user }"><p>用戶信息:{{ user.name }},年齡:{{ user.age }}</p>
</template>
12、Vuex 有哪種屬性及作用
vue2+vue3都可使用vuex
- state: 存放共享的數(shù)據(jù)屬性
- mutations: 更改 state 中的狀態(tài)()同步操作
- actions: 異步操作 獲取數(shù)據(jù)提交 mutations 來間接更新 state 數(shù)據(jù)
- getters: 類似于計(jì)算屬性,對 stated 的數(shù)據(jù)進(jìn)行計(jì)算
- model: 模塊設(shè)置,每個模塊有自己對于的 vuex 屬性
vue3 新增了一個pinia
- state 存放共享屬性
- actions 可支持同步和異步
- getters(可選):用于計(jì)算派生狀態(tài)。
- persist(可選):用于配置狀態(tài)的持久化選項(xiàng)。
13.計(jì)算屬性和監(jiān)聽的執(zhí)行順序
- 默認(rèn) beforeCreate -> props -> data -> computed -> created -> mounted -> methods
- 監(jiān)聽設(shè)置立即執(zhí)行 beforeCreate -> props -> data -> watch -> computed -> created -> mounted -> methods
- 觸發(fā)某一事件
Methods -> watch -> computed
14.以下是 Vue3 與 Vue2 在一些方面的比較:
v2的mixin與v3的hook
- 相同點(diǎn)
目的相同:Vue 2 的 Mixin 和 Vue 3 的 Hook 都旨在實(shí)現(xiàn)代碼的復(fù)用和邏輯的共享。 - 不同點(diǎn)
語法和實(shí)現(xiàn)方式
Mixin:在 Vue 2 中,通過將多個對象的屬性和方法合并到組件中來實(shí)現(xiàn)復(fù)用。
Hook:在 Vue 3 中,通過函數(shù)來封裝和返回有狀態(tài)的邏輯。
數(shù)據(jù)響應(yīng)式處理
Mixin:對于響應(yīng)式數(shù)據(jù)的處理可能相對復(fù)雜,容易出現(xiàn)一些意外情況。
Hook:基于 Vue 3 改進(jìn)的響應(yīng)式系統(tǒng),處理響應(yīng)式更加可靠和高效。
代碼組織和可讀性
Mixin:多個 Mixin 混合使用時,可能導(dǎo)致代碼結(jié)構(gòu)混亂,難以清晰地理解數(shù)據(jù)和方法的來源。
Hook:函數(shù)式的風(fēng)格使得代碼的組織更加清晰,邏輯更加內(nèi)聚。
類型支持
Hook:在 TypeScript 中的類型支持更好,更容易進(jìn)行類型推導(dǎo)和類型檢查。
響應(yīng)式原理:
- Vue2:通過 Object.defineProperty 對 data 中的屬性進(jìn)行劫持來實(shí)現(xiàn)響應(yīng)式。但存在無法監(jiān)聽數(shù)組變化、需通過特殊方法實(shí)現(xiàn),以及無法監(jiān)聽對象新增和刪除屬性等限制。
- Vue3:使用 Proxy 代替 Object.defineProperty,可以監(jiān)聽到對象的所有屬性,包括新增和刪除操作,還支持?jǐn)?shù)組的監(jiān)聽,并且使用 WeakMap 存儲依賴關(guān)系,避免了內(nèi)存泄漏問題。
性能提升:
- Vue3 在響應(yīng)式處理以及重寫 diff 算法等內(nèi)部實(shí)現(xiàn)上進(jìn)行了大量優(yōu)化,渲染速度更快,性能更好,內(nèi)存占用更少。例如采用靜態(tài)提升技術(shù),對不參與更新的元素做靜態(tài)提升,只會被創(chuàng)建一次,在渲染時直接復(fù)用,優(yōu)化內(nèi)存。在 diff 算法中增加了靜態(tài)標(biāo)記,采用同序列比對和最長遞歸子序列算法計(jì)算最小修改偏移量。
- Vue3 還支持更好的 Tree Shaking,通過模塊拆分和函數(shù)式編程,實(shí)現(xiàn)按需引入,減少打包體積;同時對源碼體積進(jìn)行了優(yōu)化,移除了一些非必要特性,新增模塊也可按需引入。
編碼方式:
- Vue3 引入了 Composition API(組合式 API),允許開發(fā)者更好地組織和復(fù)用邏輯代碼,提高代碼的可維護(hù)性??梢愿鶕?jù)邏輯相關(guān)性組織代碼,代碼量少,更靈活,語法提示友好,且對 TypeScript 的支持更好。
- Vue2 使用 Options API,組件的邏輯分散在不同的選項(xiàng)中(如 data、methods、computed 等)。
設(shè)計(jì)理念:
- Vue3 更注重模塊的拆分,模塊之間耦合度低,可獨(dú)立使用部分模塊,如只引入 reactive 模塊來使用響應(yīng)式處理。對所有 API 進(jìn)行重寫,采用函數(shù)式編程,支持更好的 Tree Shaking,精確實(shí)現(xiàn)按需引入,減少打包體積。
- Vue2 模塊的獨(dú)立性相對較弱。
特性支持:
- Vue3 支持更多特性,如片段、Teleport、Suspense 等。
- Vue2 相對較少。
生命周期:
Vue3 中的生命周期函數(shù)有所變化,例如 beforeCreate 和 created 變?yōu)?setup,beforeDestroy 改名為 beforeUnmount,destroyed 改名為 unmounted 等。并且 Vue3 的生命周期函數(shù)可以多次調(diào)用而不會覆蓋。
全局方法定義:
- Vue2 中直接在 Vue 實(shí)例上掛載全局方法。
- Vue3 中通過創(chuàng)建的應(yīng)用實(shí)例來定義全局方法。
template 根組件:
- Vue2 有且只有一個根組件。
- Vue3 沒有固定的根節(jié)點(diǎn),可以有多個根。
啟動方式:
1. Vue2:new Vue({ store, router, render: h => h(App) }).$mount("#app")
2. Vue3:import { createApp } from 'Vue'; createApp(App).use(store).use(router).mount("#App")
路由和狀態(tài)管理:
- Vue3 的路由創(chuàng)建方式和 Vue2 有所不同。在 Vue2 中創(chuàng)建路由對象實(shí)例通過 new Router,而 Vue3 是通過 import createRouter 這個函數(shù)來構(gòu)建。
- Vue3 中的狀態(tài)管理庫 Pinia 與 Vue2 中的 Vuex 也有一些區(qū)別,Pinia 去掉了 mutations 和 modules,modules 在 Pinia 中是自帶的,不需要手動去寫。
computed 計(jì)算屬性和 watch 監(jiān)聽:
- Vue2 中的 computed 寫法是在對象中定義方法,而 Vue3 中需引入 computed,寫法是一個函數(shù),需返回結(jié)果。
- Vue3 中的 watch 監(jiān)聽寫法也有所不同,第三個參數(shù)可選。對于 ref 數(shù)據(jù)的監(jiān)聽不需要加 .value,且能監(jiān)聽多個值的變化。而 ref 生成的響應(yīng)式對象默認(rèn)不支持深度監(jiān)聽,需加上 deep: true,reactive 生成的響應(yīng)式對象則默認(rèn)為深度監(jiān)聽。
props 處理:
- Vue2 中接收 props 是對象時,可添加 default、required、type 等屬性。而 Vue3 中 props 是只讀的,不能在 setup 函數(shù)中修改,如需修改可使用響應(yīng)式對象或 ref。
微信小程序
1. 登陸順序
- 調(diào)用 wx.login() 接口獲取臨時登錄憑證 code
- 拿code向后端獲取token
- 后端通過code去向微信端獲取sessionKey和openId后向前端返回登錄態(tài)也就是token
react
1.Hooks,高階組件
- useState:用于在函數(shù)組件中添加狀態(tài),可跟蹤隨時間變化的數(shù)據(jù)。它返回一個狀態(tài)值和更新該狀態(tài)值的函數(shù)。
- useEffect:用于執(zhí)行副作用操作,如數(shù)據(jù)獲取、訂閱或手動更改 DOM 等。類似于類組件中的componentDidMount、componentDidUpdate和componentWillUnmount生命周期。(沒有依賴項(xiàng)初始+更新、依賴為空初始、有依賴初始+值變)
- useRef:用于創(chuàng)建對 DOM 元素或值的引用,可以在渲染之間保持狀態(tài)。
- useMemo:用于對計(jì)算結(jié)果進(jìn)行記憶,避免在每次渲染時重復(fù)計(jì)算。只有當(dāng)依賴項(xiàng)發(fā)生變化時,才會重新計(jì)算結(jié)果。
- useReducer:用于更復(fù)雜的狀態(tài)邏輯,它接收一個 reducer 函數(shù)和初始狀態(tài),然后返回當(dāng)前的狀態(tài)和派發(fā) action 的 dispatch 函數(shù)。
- uesContet用于訪問 React Context 在組件樹中傳遞的數(shù)據(jù),而不必通過每個組件傳遞 props
- useLayoutEffect與 useEffect 類似,但它在所有的 DOM 變更之后同步執(zhí)行。這在需要讀取 DOM 布局并同步觸發(fā)重渲染時非常有用。
- useDebugValue用于在 React 開發(fā)者工具中顯示自定義 Hook 的標(biāo)簽
- useCallback:用于返回一個記憶化版本的回調(diào)函數(shù),防止不必要的渲染。它會在依賴項(xiàng)沒有變化時返回上次緩存的函數(shù)。
- useFetch(非 React 內(nèi)置 Hook):例如react-fetch-hook,用于便捷地使用fetch API進(jìn)行數(shù)據(jù)獲取。
- useWindowScrollPosition(非 React 內(nèi)置 Hook):用于獲取窗口的滾動位置。
- useLocalStorage(非 React 內(nèi)置 Hook)用于同步本地存儲的數(shù)據(jù)
總的來說,useState 關(guān)注狀態(tài)的管理和組件的重新渲染,useEffect 專注于副作用的處理,useRef 則主要用于引用和保存跨渲染的數(shù)據(jù)。
2.Redux中間件原理
在 Redux 中,數(shù)據(jù)的更新流程通常是:
action 被派發(fā) -> reducer 根據(jù) action 計(jì)算新的 state -> 新的state 更新到 store 中,從而觸發(fā)視圖的更新。
中間件位于 action 被派發(fā)和 reducer 處理之間。它本質(zhì)上是一個函數(shù),接收 Redux 里 store 的 dispatch 和 getState 方法作為參數(shù),并返回一個新的函數(shù)。這個新的函數(shù)會接收下一個中間件或者最終的 reducer 作為參數(shù)。
3.Redux異步操作
Redux Thunk:
原理:Redux Thunk 是一個中間件,它允許 action 創(chuàng)建函數(shù)返回一個函數(shù)而不是一個對象。返回的函數(shù)接收 dispatch 和 getState 方法作為參數(shù),從而可以在函數(shù)內(nèi)部進(jìn)行異步操作,并在操作完成后使用 dispatch 派發(fā)相應(yīng)的同步 action 來更新狀態(tài)。
vue、react和小程序之間的區(qū)別
1.Diff算法,react跟vue的diff區(qū)別
Diff 算法是一種用于比較兩個數(shù)據(jù)結(jié)構(gòu)差異的算法,主要用于高效地更新虛擬 DOM 以最小化對真實(shí) DOM 的操作,從而提高性能.
React 的 Diff 算法主要基于兩個假設(shè):
兩個不同類型的元素會產(chǎn)生完全不同的樹。 對于同一層級的一組子節(jié)點(diǎn),通過 key 來標(biāo)識節(jié)點(diǎn)的唯一性。
當(dāng)對比兩棵樹時,如果節(jié)點(diǎn)類型不同,直接刪除舊的節(jié)點(diǎn)并創(chuàng)建新的節(jié)點(diǎn)。對于同一類型的節(jié)點(diǎn),則比較屬性的變化來更新 DOM。
Vue 的 Diff 算法
在更新節(jié)點(diǎn)時,會更加精細(xì)化。在處理同層級節(jié)點(diǎn)對比時,會遵循以下策略: 新老節(jié)點(diǎn)數(shù)組的開始和結(jié)束位置設(shè)置指針進(jìn)行比較。 如果節(jié)點(diǎn)有 key,會根據(jù) key 進(jìn)行更準(zhǔn)確的匹配和復(fù)用。
當(dāng)新節(jié)點(diǎn)多或者老節(jié)點(diǎn)多時,會通過創(chuàng)建或刪除節(jié)點(diǎn)來達(dá)到最終的一致性。
例如,如果在 Vue 中一個列表的順序發(fā)生了變化,并且節(jié)點(diǎn)有 key ,那么 Vue 可以更準(zhǔn)確地移動節(jié)點(diǎn)而不是刪除和重新創(chuàng)建。
2.React、vue生命周期,要展開來說
react:
- Mounted掛載
Constract(初始化state)
stateFromProps
Render(計(jì)算返回虛擬dom|掛掛在和更新都會用)
ComponetDidMout(獲取數(shù)據(jù)) - 更新updating:父組件重新渲染、 setState或forceUpdate觸發(fā)
前兩個是因?yàn)楦附M件重新渲染更新的
stateFromProps
Render()
shouldComponetUpdate
ComputedDidUpdata - 卸載Unmouting
cnmponetWillUnmount(清理資源,取消定時器)
vue3:
{ setup, onBeforeMount, onMounted, onBeforeUpdate, onUpdated, onBeforeUnmount, onUnmounted }
vue2
父前三個-子前四個-父結(jié)尾
3.小程序原生父子傳值
父傳子正常傳 子properties收
子傳父taggerEvent(“fun”,value) +父bindFun+this.selectComponent(“類名”)
4.Vue,react,小程序組件間的通信
Vue:
- 導(dǎo)航+編程
- Query 參數(shù)
- params路由參數(shù)
- meta
React:
- 導(dǎo)航+編程
- props.params 方法
- query 方法:類似于表單中的 get 方法,傳遞參數(shù)為明文,但刷新頁面參數(shù)會丟失。
小程序:
- 使用 navigator 的 url 帶參傳值,利用 getCurrentPages 進(jìn)行頁面?zhèn)髦?#xff0c;
- 小程序中還可以使用 wx.navigateTo、wx.redirectTo 等方法進(jìn)行路由跳轉(zhuǎn)并傳值,它們與 navigator 的對應(yīng)關(guān)系如下:
- navigator 的 open-type=“navigate”(不寫默認(rèn)值是 navigate)等于 wx.navigateTo:保留當(dāng)前頁面,跳轉(zhuǎn)到應(yīng)用內(nèi)的某個頁面,但不能跳到 tabbar 頁面,小程序中頁面棧最多十層,可帶參。
- wx.redirectTo:關(guān)閉當(dāng)前頁面,跳轉(zhuǎn)到應(yīng)用內(nèi)的某個頁面,但不允許跳轉(zhuǎn)到 tabbar 頁面,可帶參。
- wx.switchTab:跳轉(zhuǎn)到 tabBar 頁面,并關(guān)閉其他所有非 tabBar 頁面,不可帶參。
- wx.reLaunch:關(guān)閉所有頁面,打開到應(yīng)用內(nèi)的某個頁面,可帶參。
- wx.navigateBack:關(guān)閉當(dāng)前頁面,返回上一頁面或多級頁面
5.Vue跟react的優(yōu)缺點(diǎn)
Vue 和 React 都是非常流行的前端框架,它們各自有一些優(yōu)點(diǎn)和缺點(diǎn):
Vue 的優(yōu)點(diǎn):
- 學(xué)習(xí)曲線相對較平緩容易理解和上手。
- 模板語法簡潔:Vue 的模板語法直觀,與 HTML 結(jié)構(gòu)相似,使得開發(fā)者可以更自然地編寫視圖。
- 輕量級:Vue 的核心庫相對較小,性能開銷較低。
- 漸進(jìn)式框架:可以逐步將 Vue 引入現(xiàn)有的項(xiàng)目,無需一次性進(jìn)行大規(guī)模重構(gòu)。
- 中文文檔豐富:對國內(nèi)開發(fā)者來說,查找資料和解決問題更加方便。
Vue 的缺點(diǎn): - 生態(tài)系統(tǒng)相對較小:與 React 相比,一些特定領(lǐng)域的庫和工具可能相對較少。
- 大型項(xiàng)目的可擴(kuò)展性:在處理超大型復(fù)雜應(yīng)用時,可能在架構(gòu)和擴(kuò)展方面面臨一些挑戰(zhàn)。
React 的優(yōu)點(diǎn):
- 強(qiáng)大的生態(tài)系統(tǒng):擁有大量的高質(zhì)量第三方庫和工具,幾乎可以滿足任何需求。
- 虛擬 DOM 優(yōu)化:高效的虛擬 DOM 算法,使得性能優(yōu)化更具可控性。
- 社區(qū)活躍:擁有龐大且活躍的社區(qū),技術(shù)更新和支持力度大。
- 適用于大型應(yīng)用:架構(gòu)靈活,在大型項(xiàng)目中更容易進(jìn)行代碼組織和管理。
React 的缺點(diǎn):
- 學(xué)習(xí)曲線陡峭:需要掌握較多的概念和技術(shù),如 JSX、函數(shù)式編程等。
- 代碼復(fù)雜度較高:尤其是在處理復(fù)雜的狀態(tài)管理時。
- 原生模板語法不夠直觀:JSX 對于一些開發(fā)者來說可能不太習(xí)慣。
需要注意的是,選擇 Vue 還是 React 取決于具體的項(xiàng)目需求、團(tuán)隊(duì)技術(shù)棧和個人偏好。在實(shí)際開發(fā)中,兩者都能構(gòu)建出高質(zhì)量的應(yīng)用程序。
Git
rebase
1.在基于某個分支進(jìn)行開發(fā)時,如果上游分支有新的提交,使用 rebase 可以將本地的提交重新應(yīng)用到更新后的上游分支頂端,而不是直接合并。