国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

2023前端超全面試題,全是金三銀四面試真題整理!附答案。

這篇具有很好參考價(jià)值的文章主要介紹了2023前端超全面試題,全是金三銀四面試真題整理!附答案。。希望對(duì)大家有所幫助。如果存在錯(cuò)誤或未考慮完全的地方,請(qǐng)大家不吝賜教,您也可以點(diǎn)擊"舉報(bào)違法"按鈕提交疑問(wèn)。

目錄

HTML

標(biāo)簽語(yǔ)意化

HTML5新特性

SEO

input元素的類型

iframe的特點(diǎn)

CSS

Flex

BFC

重排重繪

CSS優(yōu)先級(jí)

CSS3新特性

清除浮動(dòng)的方法

盒模型的理解

響應(yīng)式布局

移動(dòng)適配方案

三欄布局

圣杯布局和雙飛翼布局

JS

JS為何是單線程

JS數(shù)據(jù)類型

js判斷數(shù)據(jù)類型

js中的length屬性

判斷空對(duì)象

判斷空數(shù)組

ES6新特性

ES6 Module 和 CommonJS 的區(qū)別

箭頭函數(shù)和普通函數(shù)區(qū)別

new一個(gè)對(duì)象做了什么事情

構(gòu)造函數(shù)與普通函數(shù)的區(qū)別

防抖和節(jié)流

深拷貝淺拷貝

數(shù)組去重

原型鏈

call、bind、apply的含義和區(qū)別

Class

Class和構(gòu)造函數(shù)的區(qū)別

js繼承的幾種方式及其優(yōu)缺點(diǎn)

閉包

瀏覽器的緩存機(jī)制

任務(wù)隊(duì)列(宏/微任務(wù))

事件委托

請(qǐng)求

請(qǐng)求的方式有哪些,應(yīng)用場(chǎng)景是什么

什么是promise,解決了什么問(wèn)題

談?wù)剬?duì)async/await的理解

跨越問(wèn)題如何解決

輸入網(wǎng)站url地址后發(fā)生了什么

ajax工作流程及原理

axios 是什么、怎么使用

Localstorage、sessionStorage、cookie 的區(qū)別

后端接口沒(méi)寫出來(lái),前端如何進(jìn)行開發(fā)

post請(qǐng)求和get請(qǐng)求的區(qū)別

Session,Token,Cookie在身份認(rèn)證方面的區(qū)別

常見的狀態(tài)碼

Vue2

Vue是什么

MVVM

觀察者模式和發(fā)布訂閱者模式

SPA(單頁(yè)應(yīng)用)的理解

響應(yīng)式原理

Vue2生命周期

data為什么是函數(shù)的存在

Vue組件通信的方式

keep-alive原理及緩存策略

computed原理

watch原理

computed和methods、watch的區(qū)別

vue-router原理

Vue3

Vue2和Vue3響應(yīng)式原理的區(qū)別

Vue3生命周期

選項(xiàng)式API和組合式API

VueX和Pinia的區(qū)別、優(yōu)劣

Vite好在哪為什么

TS

對(duì)ts的理解

ts的數(shù)據(jù)類型

never和void的區(qū)別

枚舉的理解

泛型

項(xiàng)目

token超時(shí)處理

登錄頁(yè)面安全問(wèn)題

發(fā)布通知功能怎么實(shí)現(xiàn)

項(xiàng)目剛上線出現(xiàn)bug

用什么進(jìn)行版本管理

Echarts在Vue里怎么使用

Echarts里的配置項(xiàng)不夠用怎么辦

團(tuán)隊(duì)中有的人用vue2有的人用vue3怎么辦

項(xiàng)目?jī)?yōu)化

PC端兼容問(wèn)題

img下的留白

如果圖片加a標(biāo)簽在IE9-中會(huì)有邊框

移動(dòng)端問(wèn)題

移動(dòng)端頁(yè)面滾動(dòng)滯澀感

修改移動(dòng)端的點(diǎn)擊高亮效果

滾動(dòng)穿透問(wèn)題

在ios和andriod中,audio元素和video元素在無(wú)法自動(dòng)播放

iOS 系統(tǒng)中文輸入法輸入英文時(shí),字母之間可能會(huì)出現(xiàn)一個(gè)六分之一空格

IOS移動(dòng)端click事件300ms的延遲響應(yīng)

阻止旋轉(zhuǎn)屏幕時(shí)自動(dòng)調(diào)整字體大小

圖片模糊問(wèn)題

移動(dòng)端某些情況下input的placeholder會(huì)出現(xiàn)文本位置偏上的現(xiàn)象

h5底部輸入框被鍵盤遮擋問(wèn)題

移動(dòng)端如何做真機(jī)測(cè)試

H5和app的區(qū)別


HTML

標(biāo)簽語(yǔ)意化

簡(jiǎn)單來(lái)說(shuō):就是用正確的標(biāo)簽做正確的事。比如:

  • 頭部:header

  • 導(dǎo)航:nav

  • 主體內(nèi)容:main

  • 標(biāo)題:h1 ~ h6

  • 段落:p

  • 側(cè)邊欄:aside

  • 頁(yè)腳:footer

這樣,整篇HTML結(jié)構(gòu)非常清晰,好看。

HTML語(yǔ)義化有什么好處呢?

  • 網(wǎng)頁(yè)加載慢導(dǎo)致CSS文件還未加載時(shí)(沒(méi)有CSS),頁(yè)面仍然清晰、可讀、好看。

  • 提升用戶體驗(yàn),例如title、alt可用于解釋名詞或解釋圖片信息。

  • 有利于SEO:和搜索引擎建立良好溝通,有助于爬蟲抓取更多的有效信息。

  • 方便其他設(shè)備(如屏幕閱讀器、盲人閱讀器、移動(dòng)設(shè)備)更好的解析頁(yè)面。

  • 使代碼更具可讀性,便于團(tuán)隊(duì)開發(fā)和維護(hù)。

HTML5新特性

  • 更加語(yǔ)義化的元素。 article、footer、header、nav、section

  • 本地化儲(chǔ)存。 localStorage 和 sessionStorage

  • 拖曳以及釋放的api。 Drag and drop(draggable="true";當(dāng)拖拽一個(gè)項(xiàng)目到 HTML 元素中時(shí),瀏覽器默認(rèn)不會(huì)有任何響應(yīng)。想要讓一個(gè)元素變成可釋放區(qū)域,該元素必須設(shè)置 ondragover和 ondrop 事件。)

  • 媒體播放。 video 和 audio

  • 增強(qiáng)表單控件類型。date、time、number、email、color、search

  • 全雙工通信協(xié)議。 websocket

  • 跨域資源共享(CORS) Access-Control-Allow-Origin

補(bǔ)充:Web Storage 的概念和 cookie 相似,區(qū)別是它是為了更大容量存儲(chǔ)設(shè)計(jì)的。Cookie 的大小是受限的,并且每次你請(qǐng)求一個(gè)新的頁(yè)面的時(shí)候 Cookie 都會(huì)被發(fā)送過(guò)去,這樣無(wú)形中浪費(fèi)了帶寬,另外 cookie 還需要指定作用域,不可以跨域調(diào)用。

1.localStorage: 用于持久化的本地存儲(chǔ),除非主動(dòng)刪除數(shù)據(jù),否則數(shù)據(jù)是永遠(yuǎn)不會(huì)過(guò)期的。

2.sessionStorage: 用于本地存儲(chǔ)一個(gè)會(huì)話(session)中的數(shù)據(jù),這些數(shù)據(jù)只有在同一個(gè)會(huì)話中的頁(yè)面才能訪問(wèn)并且當(dāng)會(huì)話結(jié)束后數(shù)據(jù)也隨之銷毀。因此 sessionStorage 不是一種持久化的本地存儲(chǔ),僅僅是會(huì)話級(jí)別的存儲(chǔ)。

Web Storage 擁有 setItem,getItem,removeItem,clear 等方法,不像 cookie 需要前端開發(fā)者自己封裝 setCookie,getCookie(安裝依賴js-cookie、Cookies.set()、Cookies.get()、Cookies.remove)

SEO

SEO(Search Engine Optimization),即搜索引擎優(yōu)化。SEO的存在就是為了提升網(wǎng)站在搜索引擎中的權(quán)重,增加對(duì)搜索引擎的友好度,使得用戶在訪問(wèn)網(wǎng)站時(shí)能排在前面。

  • 突出重要內(nèi)容---合理的設(shè)計(jì)title、descriptionkeywords

  • 語(yǔ)義化書寫HTML代碼,符合W3C標(biāo)準(zhǔn)

  • 圖片img標(biāo)簽添加alttitle屬性

  • 鏈接<a>頁(yè)內(nèi)標(biāo)簽添加title屬性

  • 使用h1標(biāo)簽自帶權(quán)重

input元素的類型

① button ② checkbox ③ file ④ hidden ⑤ image ⑥ password ⑦ radio ⑧ reset ⑨ submit ⑩ Text ? Date

iframe的特點(diǎn)

  • 優(yōu)點(diǎn):

  1. iframe能夠原封不動(dòng)的把嵌入的網(wǎng)頁(yè)展現(xiàn)出來(lái)。

  2. 如果有多個(gè)網(wǎng)頁(yè)引用iframe,那么你只需要修改iframe的內(nèi)容,就可以實(shí)現(xiàn)調(diào)用的每一個(gè)頁(yè)面內(nèi)容的更改,方便快捷。

  3. 網(wǎng)頁(yè)如果為了統(tǒng)一風(fēng)格,頭部和版本都是一樣的,就可以寫成一個(gè)頁(yè)面,用iframe來(lái)嵌套,可以增加代碼的可重用。

  4. 如果遇到加載緩慢的第三方內(nèi)容如圖標(biāo)和廣告,這些問(wèn)題可以由iframe來(lái)解決。

  • 缺點(diǎn):

  1. iframe會(huì)阻塞主頁(yè)面的onload事件;

  2. iframe和主頁(yè)面共享連接池,而瀏覽器對(duì)相同域的連接有限制,所以會(huì)影響頁(yè)面的并行加載。,會(huì)產(chǎn)生很多頁(yè)面,不容易管理。

  3. iframe框架結(jié)構(gòu)有時(shí)會(huì)讓人感到迷惑,如果框架個(gè)數(shù)多的話,可能會(huì)出現(xiàn)上下、左右滾動(dòng)條,會(huì)分散訪問(wèn)者的注意力,用戶體驗(yàn)度差。

  4. 代碼復(fù)雜,無(wú)法被一些搜索引擎索引到,這一點(diǎn)很關(guān)鍵,現(xiàn)在的搜索引擎爬蟲還不能很好的處理iframe中的內(nèi)容,所以使用iframe會(huì)不利于搜索引擎優(yōu)化(SEO)。

  5. 很多的移動(dòng)設(shè)備無(wú)法完全顯示框架,設(shè)備兼容性差。

  6. iframe框架頁(yè)面會(huì)增加服務(wù)器的http請(qǐng)求,對(duì)于大型網(wǎng)站是不可取的。

CSS

Flex

  • 哪些屬性作用在父元素上?

justify-content:space-around space-between space-evently center flex-end

align-items:flex-star flex-end

flex-direction :row row-reverse column column-reverse

flex-wrap :nowrap(如果子孩子,的寬度超過(guò)父盒子,會(huì)進(jìn)行總動(dòng)的伸縮) wrap(不去管)

  • 哪些屬性作用在子元素上?

order (項(xiàng)目排列的順序 越小越靠前)

align-self(單個(gè)屬性的操作 flex-end center flex-star)

flex-grow(如果剩余有寬度是否進(jìn)行擴(kuò)張方法,默認(rèn)是0,)

flex-shrink (空間不足的時(shí)候進(jìn)行縮小默認(rèn)是1 進(jìn)行縮?。?/p>

BFC

定義:

塊級(jí)格式化上下文。BFC是一個(gè)完全獨(dú)立的空間(布局環(huán)境),讓空間里的子元素不會(huì)影響到外面的布局。用于對(duì)塊級(jí)元素排版。默認(rèn)情況下只有根元素(body)一個(gè)塊級(jí)上下文。

布局規(guī)則:

  • 內(nèi)部的盒子會(huì)在垂直方向,一個(gè)個(gè)地放置;

  • 盒子垂直方向的距離由 margin 決定,屬于同一個(gè) BFC 的兩個(gè)相鄰盒子的上下 margin 會(huì)發(fā)生重疊;

  • 每一個(gè)元素的左邊,與包含塊的左邊相接觸(對(duì)于從右往左的布局,則相反),即使存在浮動(dòng)也是如此;

  • BFC 的區(qū)域不會(huì)與 float 重疊;(應(yīng)用:三欄布局)

  • BFC 就是頁(yè)面上的一個(gè)隔離的獨(dú)立容器,容器里面的子元素不會(huì)影響到外面的元素。反之也如此;

  • 計(jì)算 BFC 的高度時(shí),浮動(dòng)元素也參與計(jì)算。(運(yùn)用:清除浮動(dòng))

  • 當(dāng)一個(gè)元素設(shè)置了新的 BFC 后,就和這個(gè)元素外部的 BFC 沒(méi)有關(guān)系了,這個(gè)元素只會(huì)去約束自己內(nèi)部的子元素。(應(yīng)用:外邊距塌陷)

怎么觸發(fā)BFC:

  • overflow:不為 visible;

  • float: 不為 none;

  • display: 為 inline-block、table、table-cell、table-captionflex、inline-flex、grid、inline-grid、flow-root;

  • position: 為 absolute 或者 fixed;

重排重繪

頁(yè)面生成的過(guò)程:

1.HTML 被 HTML 解析器解析成 DOM 樹;

2.CSS 被 CSS 解析器解析成 CSSOM 樹;

3.結(jié)合 DOM 樹和 CSSOM 樹,生成一棵渲染樹(Render Tree),這一過(guò)程稱為 Attachment;

4.生成布局(flow),瀏覽器在屏幕上“畫”出渲染樹中的所有節(jié)點(diǎn);

5.將布局繪制(paint)在屏幕上,顯示出整個(gè)頁(yè)面。

第四步和第五步是最耗時(shí)的部分,這兩步合起來(lái),就是我們通常所說(shuō)的渲染。

2023前端超全面試題,全是金三銀四面試真題整理!附答案。

  • 重繪:某些元素的外觀被改變,例如:元素的填充顏色

  • 重排:重新生成布局,重新排列元素。

單單改變?cè)氐耐庥^,肯定不會(huì)引起網(wǎng)頁(yè)重新生成布局,但當(dāng)瀏覽器完成重排之后,將會(huì)重新繪制受到此次重排影響的部分。比如改變?cè)馗叨?,這個(gè)元素乃至周邊dom都需要重新繪制。

也就是說(shuō):重繪不一定導(dǎo)致重排,但重排一定會(huì)導(dǎo)致重繪

CSS優(yōu)先級(jí)

!important > style > id > class > 標(biāo)簽 > 通配符 > 默認(rèn) > 繼承

CSS3新特性

  1. 新增的選擇器(各種偽類選擇器)

  2. 圓角(border-radius)

  3. 陰影(box-shadow)

  4. 動(dòng)畫(animation)

  5. 過(guò)渡(transition)

  6. 翻轉(zhuǎn)(transform)

  7. 漸變

  8. 媒體查詢 @media

  9. 彈性盒子(flex)

  10. rgba

清除浮動(dòng)的方法

為什么要清除浮動(dòng)?

如果子元素浮動(dòng),此時(shí)子元素不能撐開標(biāo)準(zhǔn)流的塊級(jí)父元素。

方法:

1、直接給父元素設(shè)置高度

  • 優(yōu)點(diǎn):簡(jiǎn)單、方便

  • 缺點(diǎn):有很多布局不能固定父元素高度:比如長(zhǎng)列表、推薦模塊,是無(wú)法確定子項(xiàng)內(nèi)容有多少的

2、額外標(biāo)簽法

  • 實(shí)現(xiàn)方式:

    1. 給父元素內(nèi)容的最后添加一個(gè)塊級(jí)元素

    2. 給添加的塊級(jí)元素設(shè)置clear: both;(可以認(rèn)為,設(shè)置了clear:both的當(dāng)前元素會(huì)把前邊元素中設(shè)有浮動(dòng)屬性的元素,當(dāng)做沒(méi)設(shè)浮動(dòng)一樣來(lái)看待,以此來(lái)消除其對(duì)自己的影響)

  • 缺點(diǎn):

    • 會(huì)添加進(jìn)去額外的標(biāo)簽,讓HTML結(jié)構(gòu)變得復(fù)雜

3、單偽元素清除法

用偽元素替代額外標(biāo)簽

4、雙偽元素清除法

除了可以清除浮動(dòng)的影響,還可以解決外邊距折疊的塌陷現(xiàn)象(原理:里面的"display:table;"觸發(fā)BFC)

5、為父元素設(shè)置overflow: hidden

盒模型的理解

分標(biāo)準(zhǔn)盒模型和怪異盒模型。

標(biāo)準(zhǔn)盒模型采用的W3C標(biāo)準(zhǔn),盒子的content內(nèi)容部分由width寬度和height高度決定,添加padding內(nèi)邊距或border外邊框后,寬高都會(huì)進(jìn)行相應(yīng)增長(zhǎng)。

怪異盒模型也稱為IE盒模型,是IE瀏覽器設(shè)計(jì)元素時(shí)遵循的規(guī)則。怪異盒模型的寬高在div盒子初次設(shè)置時(shí)就已經(jīng)規(guī)定,添加padding或者border,會(huì)從中減少content內(nèi)容的占據(jù)區(qū)域,來(lái)為padding和border制造空間,寬高不會(huì)相對(duì)應(yīng)的進(jìn)行增長(zhǎng)。

盒模型轉(zhuǎn)換用box-sizing:border-box,默認(rèn)是標(biāo)準(zhǔn)盒模型。

響應(yīng)式布局

  • bootstrop框架

  • 媒體查詢

移動(dòng)適配方案

  • rem(用flexible方案,flexible.js幫我們計(jì)算出1rem 等于多少px)

  • vw和vh

三欄布局

  • flex

  • 定位

  • 浮動(dòng)

    • 兩邊浮動(dòng)中間margin + overflow: hidden(觸發(fā)BFC)

    • 兩邊浮動(dòng),中間calc()函數(shù)

    • 三個(gè)部分都浮動(dòng)(圣杯和雙飛翼布局),然后結(jié)合margin和定位調(diào)整

  • display:table;

  • grid布局

圣杯布局和雙飛翼布局

最后我們來(lái)總結(jié)一下,雙飛翼布局其實(shí)和圣杯布局的精髓是一樣的,都是在三個(gè)部分都是浮動(dòng)的情況下,左右的部分因?yàn)楦负凶訉挾炔粔虮粩D下來(lái)的問(wèn)題,通過(guò)設(shè)置負(fù)margin來(lái)實(shí)現(xiàn)元素的排布。

  • 不同的就是html結(jié)構(gòu),雙飛翼是在middle元素內(nèi)部又設(shè)置了一個(gè)milddle-inner并設(shè)置它的左右margin,而非圣杯布局的padding,來(lái)排除兩邊元素的覆蓋,最后把盒子定位到兩側(cè)。

  • 雙飛翼布局可以多了一個(gè)html結(jié)構(gòu),但是可以不用設(shè)置left,right元素的定位。

JS

JS為何是單線程

JavaScript的單線程,與它的用途有關(guān)。作為瀏覽器腳本語(yǔ)言,JavaScript的主要用途是與用戶互動(dòng),以及操作DOM。這決定了它只能是單線程,否則會(huì)帶來(lái)很復(fù)雜的同步問(wèn)題。比如,假定JavaScript同時(shí)有兩個(gè)線程,一個(gè)線程在某個(gè)DOM節(jié)點(diǎn)上添加內(nèi)容,另一個(gè)線程刪除了這個(gè)節(jié)點(diǎn),這時(shí)瀏覽器應(yīng)該以哪個(gè)線程為準(zhǔn)?

所以,為了避免復(fù)雜性,從一誕生,JavaScript就是單線程,這已經(jīng)成這門語(yǔ)言的核心特征,將來(lái)也不會(huì)改變。

注:所謂單線程,是指在JS引擎中負(fù)責(zé)解釋和執(zhí)行JavaScript代碼的線程只有一個(gè)。

JS數(shù)據(jù)類型

基本類型分為以下六種:

  • string(字符串)

  • boolean(布爾值)

  • number(數(shù)字)

  • symbol(符號(hào))

  • null(空值)

  • undefined(未定義)

  • BigInt(是ES6中新引入的數(shù)據(jù)類型,它是一種內(nèi)置對(duì)象,它提供了一種方法來(lái)表示表示任意大的整數(shù)。即使這個(gè)數(shù)已經(jīng)超出了JavaScript構(gòu)造函數(shù) Number 能夠表示的安全整數(shù)范圍。)

引用數(shù)據(jù)類型:

  • 數(shù)組

  • 對(duì)象(函數(shù)也是對(duì)象)

區(qū)別:

值類型的變量會(huì)保存在 棧內(nèi)存 中,如果在一個(gè)函數(shù)中聲明一個(gè)值類型的變量,那么這個(gè)變量當(dāng)函數(shù)執(zhí)行結(jié)束之后會(huì) 自動(dòng)銷毀。

引用類型的變量名會(huì)保存在 棧內(nèi)存 中,但是變量值會(huì)存儲(chǔ)在 堆內(nèi)存 中,引用類型的變量不會(huì)自動(dòng)銷毀,當(dāng)沒(méi)有引用變量引用它時(shí),系統(tǒng)的 垃圾回收機(jī)制 會(huì)回收它。

js判斷數(shù)據(jù)類型

判斷數(shù)據(jù)類型方法有很多,實(shí)際使用需要根據(jù)自己的需求使用最適合自己的方法

1、使用 typeof

測(cè)試簡(jiǎn)單數(shù)據(jù)類型。對(duì)于null及數(shù)組、對(duì)象,typeof均檢測(cè)出為object,不能進(jìn)一步判斷它們的類型。

2、使用 obj instanceof Object

測(cè)試復(fù)雜數(shù)據(jù)類型,因?yàn)閕nstanceof 是用來(lái)判斷數(shù)據(jù)是否是某個(gè)對(duì)象的實(shí)例

所以對(duì)于 nullundefined 這兩個(gè)家伙就檢測(cè)不了

因?yàn)樵玩溊^承的關(guān)系,instanceof 會(huì)把數(shù)組都識(shí)別為 Object 對(duì)象,所有引用類型的祖先都是 Object 對(duì)象

3、使用Object.prototype.toString.call

Object.prototype.toString.call() 區(qū)分的數(shù)據(jù)類型適用范圍更大,但是無(wú)法區(qū)分自定義對(duì)象類型,區(qū)分自定義對(duì)象類型使用 instanceof 操作符。

Object.prototype.toString()本身是允許被修改的,而我們目前所討論的關(guān)于Object.prototype.toString()這個(gè)方法的應(yīng)用都是假設(shè)toString()方法未被修改為前提的。

因?yàn)閷?shí)例對(duì)象有可能會(huì)自定義toString()方法,會(huì)覆蓋Object.prototype.toString(), 所以在使用時(shí),最好加上call()。

4、使用.constructor

constructor不能判斷undefined和null,并且使用它是不安全的,因?yàn)閏ontructor的指向是可以改變的

js中的length屬性

1、length屬性常見于字符串和數(shù)組,來(lái)判斷長(zhǎng)度。

2、length屬性還可以用于函數(shù),來(lái)判斷函數(shù)的長(zhǎng)度,即函數(shù)中形參的個(gè)數(shù)。

注意:

  • ...args不計(jì)入形參個(gè)數(shù)

  • 設(shè)置了默認(rèn)值的參數(shù)及其之后的所有參數(shù)都不計(jì)入形參個(gè)數(shù),之前的仍舊計(jì)入

判斷空對(duì)象

所謂空對(duì)象,就是數(shù)組的長(zhǎng)度等于0

let obj = {name : '你好'}
//是true為空對(duì)象,是false則不是空對(duì)象
console.log(JSON.stringify(obj) === '{}');//false
let obj = {}
?
let fn = (obj) => {
 ? ?for(let key in obj) {
 ? ? ? ?return false 
 ?  }
?
 ? ?return true
}
//返回false代表不為空,返回true則為空對(duì)象
 console.log(fn(obj));//true
let ?obj = {name : '1'}
?
//Object.getOwnPropertyNames()獲取到對(duì)象中的全部屬性名,存到一個(gè)數(shù)組中
let s = Object.getOwnPropertyNames(obj)
console.log(s); //['name'] ? //為[],代表空對(duì)象
let ?obj = {name : '1'}
//Object.keys()獲取給定對(duì)象的所有可枚舉屬性的字符串?dāng)?shù)組
let s = Object.keys(obj)
console.log(s);//[ 'name' ]  //若為[],則為空對(duì)象
let ?obj = {name : '1'}
// 注意for...in 會(huì)將對(duì)象原型鏈上的屬性也枚舉出來(lái),所以要借hasOwnProperty()方法來(lái)判斷是不是對(duì)象本身的屬性
// 如果存在返回true,不存在返回false
let fn = (s) => {
 ? ?for(let key in s) {
 ? ? ? ?if(s.hasOwnProperty(key)) {
 ? ? ? ? ? ?return false
 ? ? ?  }
 ? ? ? ?return true
 ?  }
}
console.log(fn(obj));//false ? //若是反回true則就是空對(duì)象

判斷空數(shù)組

和判斷空對(duì)象類似的,我們只要能驗(yàn)證這個(gè)對(duì)象的keys長(zhǎng)度是0,那就是個(gè)空對(duì)象了。

Array.isArray(arr) & arr.length === 0

ES6新特性

  1. 新的定義變量的方式 let const var 的區(qū)別

  2. 模板字符串

  3. class

  4. Promise

  5. async/await

  6. 箭頭函數(shù)

  7. 新的數(shù)組方法 filter some map every forEach reduce Array.from() find findIndex includes flat

  8. 拓展運(yùn)算符

  9. 賦值解構(gòu)運(yùn)算符

  10. Proxy

  11. 對(duì)象新增方法 Object.assign() Object.keys()

  12. es6的模塊化

  13. Set

  14. Map

ES6 Module 和 CommonJS 的區(qū)別

CommonJS 是對(duì)模塊的淺拷貝;ES6 Module 是對(duì)模塊的引用,即 ES6。

CommonJS是動(dòng)態(tài)編譯,可以放在代碼里動(dòng)態(tài)執(zhí)行;ES6 Module 是靜態(tài)編譯,引用只能放在最前面。

箭頭函數(shù)和普通函數(shù)區(qū)別

  1. this指向(普通函數(shù)指向調(diào)用者,this指向父級(jí)作用域的this)

  2. 不可以被當(dāng)做構(gòu)造函數(shù)

  3. 不可以使用arguments對(duì)象,該對(duì)象在函數(shù)體內(nèi)不存在,如果要用就用剩余參數(shù)替代

  4. 沒(méi)有prototype屬性

new一個(gè)對(duì)象做了什么事情

  1. new構(gòu)建函數(shù)可以在內(nèi)存中創(chuàng)建一個(gè)空的對(duì)象

  2. this會(huì)指向剛才創(chuàng)建的空對(duì)象

  3. 執(zhí)行構(gòu)造函數(shù)的代碼給這個(gè)空對(duì)象添加屬性和方法

  4. 返回這個(gè)對(duì)象(所以構(gòu)造函數(shù)不需要return)

構(gòu)造函數(shù)與普通函數(shù)的區(qū)別

1.構(gòu)造函數(shù)就是一個(gè)普通的函數(shù),創(chuàng)建方法和普通函數(shù)沒(méi)有區(qū), 不同的是構(gòu)造函數(shù)習(xí)慣上首字母大寫。

2.構(gòu)造函數(shù)與普通函數(shù)的區(qū)別就是調(diào)用方式不同,普通函數(shù)直接調(diào)用,而構(gòu)造函數(shù)使用new關(guān)鍵字調(diào)用。

防抖和節(jié)流

  • 防抖debounce

    定義:觸發(fā)高頻事件后n秒內(nèi)函數(shù)只會(huì)執(zhí)行最后一次,如果n秒內(nèi)高頻事件再次被觸發(fā),則重新計(jì)算時(shí)間。

    原理:每次觸發(fā)事件時(shí)都取消之前的延時(shí)調(diào)用方法

    function debounce(fn) {
     ?let timer = null; // 創(chuàng)建一個(gè)標(biāo)記用來(lái)存放定時(shí)器的返回值
     ?return function () {
     ? ?// 執(zhí)行這個(gè)函數(shù)之前先清掉定時(shí)器
     ? ?clearTimeout(timer);
     ? ?timer = setTimeout(() => {
     ? ? ?// 綁定this的原因是為了讓this指向正確
     ? ? ?// 綁定arguments的原因是為了正確使用函數(shù)參數(shù)位置的事件對(duì)象e
     ? ? ?fn.apply(this, arguments);
     ?  }, 500);
      };
    }

    應(yīng)用場(chǎng)景

    1. 搜索框輸入查詢,如果用戶一直在輸入中,沒(méi)有必要不停地調(diào)用去請(qǐng)求服務(wù)端接口,等用戶停止輸入的時(shí)候,再調(diào)用,設(shè)置一個(gè)合適的時(shí)間間隔,有效減輕服務(wù)端壓力。

    2. 表單驗(yàn)證

    3. 按鈕提交事件。

    4. 瀏覽器窗口縮放,resize事件(如窗口停止改變大小之后重新計(jì)算布局)等

  • 節(jié)流throttle

    定義:高頻事件觸發(fā),但在n秒內(nèi)只會(huì)執(zhí)行一次,所以節(jié)流會(huì)稀釋函數(shù)的執(zhí)行頻率

    原理:每次觸發(fā)事件時(shí)都判斷當(dāng)前是否有等待執(zhí)行的延時(shí)函數(shù)

    方法一:
    function throttle(func, wait) {
     ? ?var prev = 0;
     ? ?return function() {
     ? ? ? ?let now = Date.now();
     ? ? ? ?if (now - prev > wait) {
     ? ? ? ? ? ?func();
     ? ? ? ? ? ?// 重置起始時(shí)間
     ? ? ? ? ? ?prev = now;
     ? ? ?  }
     ?  }
    }
    方法二:
    function throttle(fn) {
     ?// 閉包保存是否可以開啟定時(shí)器,默認(rèn)是開啟的
     ?let canRun = true;
     ?return function () {
     ? ?// 如果沒(méi)有開啟就直接返回
     ? ?if (!canRun) return;
     ? ?// 開啟了就立即關(guān)閉定時(shí)器入口,然后開啟定時(shí)器
     ? ?canRun = false;
     ? ?setTimeout(() => {
     ? ? ?fn.apply(this, arguments);
     ? ? ?// 定時(shí)器運(yùn)行后,下次定時(shí)器才可開啟
     ? ? ?canRun = true;
     ?  }, 500);
      };
    }

    應(yīng)用場(chǎng)景

    1. 按鈕點(diǎn)擊事件

    2. 拖拽事件

    3. onScoll

    4. 計(jì)算鼠標(biāo)移動(dòng)的距離(mousemove)

深拷貝淺拷貝

  • 淺拷貝

    1. 展開運(yùn)算符...

      const array = [{ type: '??' }, '??', '??']
      const copyArray = [...array]
      ?
      array[0].type = '??' // 修改原數(shù)組
      console.log(array, copyArray) // 原數(shù)組和復(fù)制的數(shù)組都變成了[{ type: '??' }, '??', '??']
    2. Object.assign()

      const array = [{ type: '??' }, '??', '??']
      const copyArray = Object.assign([], array)
      ?
      array[0].type = '??' // 修改原數(shù)組
      console.log(array, copyArray) // 原數(shù)組和復(fù)制的數(shù)組都變成了[{ type: '??' }, '??', '??']
    3. Array.prototype.concat()

      const array = [{ type: '??' }, '??', '??']
      const copyArray = array.concat([])
      ?
      array[0].type = '??' // 修改原數(shù)組
      console.log(array, copyArray) // 原數(shù)組和復(fù)制的數(shù)組都變成了[{ type: '??' }, '??', '??']
    4. Array.prototype.slice()

      const array = [{ type: '??' }, '??', '??']
      const copyArray = array.slice()
      ?
      array[0].type = '??' // 修改原數(shù)組
      console.log(array, copyArray) // 原數(shù)組和復(fù)制的數(shù)組都變成了[{ type: '??' }, '??', '??']
    5. Array.from()

      const array = [{ type: '??' }, '??', '??']
      const copyArray = Array.from(array)
      ?
      array[0].type = '??' // 修改原數(shù)組
      console.log(array, copyArray) // 原數(shù)組和復(fù)制的數(shù)組都變成了[{ type: '??' }, '??', '??']
  • 深拷貝

    1、JSON.parse(JSON.stringify(obj))

    • 會(huì)忽略u(píng)ndefined Symbol

    • 不能序列化函數(shù)

    • 不能解決循環(huán)引用的對(duì)象

    • 不能正確處理 new Date()

    • 不能處理正則

    2、淺拷貝+遞歸

    module.exports = function clone(target) {
     ? ?if (typeof target === 'object') {
     ? ? ? ?let cloneTarget = Array.isArray(target) ? [] : {};
     ? ? ? ?for (const key in target) {
     ? ? ? ? ? ?cloneTarget[key] = clone(target[key]);
     ? ? ?  }
     ? ? ? ?return cloneTarget;
     ?  } else {
     ? ? ? ?return target;
     ?  }
    };

數(shù)組去重

對(duì)于 JS 數(shù)組去重來(lái)說(shuō),其實(shí)萬(wàn)變不離其中,我簡(jiǎn)單的總結(jié)了以下 4 種去重類型

1、數(shù)組元素比較型:

該方法是將數(shù)組的值取出與其他值比較并修改數(shù)組

  • 雙層 for 循環(huán)

取出一個(gè)元素,將其與其后所有元素比較,若在其后發(fā)現(xiàn)相等元素,則將后者刪掉

function uniq(arr) {
 ? ?for (let i = 0; i < arr.length; i++) {
 ? ? ? ?for (let j = i + 1; j < arr.length; j++) {
 ? ? ? ? ? ?if (arr[i] === arr[j]) {
 ? ? ? ? ? ? ? ?arr.splice(j, 1);
 ? ? ? ? ? ? ? ?j--;
 ? ? ? ? ?  }
 ? ? ?  }
 ?  }
 ? ?return arr;
}

// 運(yùn)行結(jié)果
// [1, "1", "a", {}, {}, { a: 1 }, {}, { a: 1 }, [], [], [1], undefined, null, NaN, NaN]
// 與 lodash 結(jié)果相比 NaN 沒(méi)有去掉
復(fù)制代碼
由于 NaN === NaN 等于 false,所以重復(fù)的 NaN 并沒(méi)有被去掉
 
  • 排序并進(jìn)行相鄰比較

先對(duì)數(shù)組內(nèi)元素進(jìn)行排序,再對(duì)數(shù)組內(nèi)相鄰的元素兩兩之間進(jìn)行比較,經(jīng)測(cè)試,該方法受限于 sort 的排序能力,所以若數(shù)組不存在比較復(fù)雜的對(duì)象(復(fù)雜對(duì)象難以排序),則可嘗試此方法

function uniq(arr) {
 ? ?arr.sort();
 ? ?for (let i = 0; i < arr.length - 1; i++) {
 ? ? ? ?arr[i] === arr[i + 1] && arr.splice(i + 1, 1) && i--;
 ?  }
 ? ?return arr;
}
// 運(yùn)行結(jié)果
//[[], [], 1, "1", [1], NaN, NaN, {}, {}, { a: 1 }, {}, { a: 1 }, "a", null, undefined];
// 與 lodash 結(jié)果相比 NaN 沒(méi)有去掉,且對(duì)象的去重出現(xiàn)問(wèn)題

同樣由于 NaN === NaN 等于 false,所以重復(fù)的 NaN 并沒(méi)有被去掉,并且由于 sort 沒(méi)有將對(duì)象很好的排序,在對(duì)象部分,會(huì)出現(xiàn)一些去重失效

2、查找數(shù)組元素位置型:

該類型即針對(duì)每個(gè)數(shù)組元素進(jìn)行一次查找其在數(shù)組內(nèi)的第一次出現(xiàn)的位置,若第一次出現(xiàn)的位置等于該元素此時(shí)的索引,即收集此元素

  • indexOf

indexOf 來(lái)查找元素在數(shù)組內(nèi)第一次出現(xiàn)的位置,若位置等于當(dāng)前元素的位置,則收集

function uniq(arr) {
 ? ?let res = [];
 ? ?for (let i = 0; i < arr.length; i++) {
 ? ? ? ?if (arr.indexOf(arr[i]) === i) {
 ? ? ? ? ? ?res.push(arr[i]);
 ? ? ?  }
 ?  }
 ? ?return res;
}
// 運(yùn)行結(jié)果
// [1, "1", "a", {}, {}, { a: 1 }, {}, { a: 1 }, [], [], [1], undefined, null];
// 與 lodash 結(jié)果相比 少了 NaN

indexOf 采用與 === 相同的值相等判斷規(guī)則,所以在數(shù)組內(nèi)沒(méi)有元素與 NaN 相等,包括它自己,所以 NaN 一個(gè)都不會(huì)被留下

  • findIndex

findIndex 方法來(lái)查找元素在數(shù)組內(nèi)第一次出現(xiàn)的位置

function uniq(arr) {
 ? ?let res = [];
 ? ?for (let i = 0; i < arr.length; i++) {
 ? ? ? ?if (arr.findIndex(item => item === arr[i]) === i) {
 ? ? ? ? ? ?res.push(arr[i]);
 ? ? ?  }
 ?  }
 ? ?return res;
}
// 運(yùn)行結(jié)果
// [1, "1", "a", {}, {}, { a: 1 }, {}, { a: 1 }, [], [], [1], undefined, null];
// 與 lodash 結(jié)果相比 少了 NaN

結(jié)果原理和 indexOf 相同,因?yàn)橛昧?=== 的規(guī)則來(lái)判斷元素是否相等,但此方法相當(dāng)于雙層 for 循環(huán)

3、查找元素是否存在型:

該方法基本依托 includes 方法來(lái)判斷對(duì)應(yīng)元素是否在新數(shù)組內(nèi)存在,若不存在則收集

function uniq(arr) {
 ? ?let res = [];
 ? ?for (let i = 0; i < arr.length; i++) {
 ? ? ? ?if (!res.includes(arr[i])) {
 ? ? ? ? ? ?res.push(arr[i]);
 ? ? ?  }
 ?  }
 ? ?return res;
}
// 運(yùn)行結(jié)果
// [1, "1", "a", {}, {}, { a: 1 }, {}, { a: 1 }, [], [], [1], undefined, null, NaN];
// 與 lodash 結(jié)果相同

includes 方法采用 SameValueZero 判斷規(guī)則,所以可以判斷出并去重 NaN

4、依托數(shù)據(jù)類型特性型:

該方案依托于數(shù)據(jù)類型的不重復(fù)特性,以達(dá)到去重效果

  • Map

Map 類型的數(shù)據(jù)可以像 Object 一樣,在設(shè)定元素鍵值對(duì)的時(shí)候可以保證鍵的唯一,并且將鍵的類型拓展到了基本所有元素,包括對(duì)象,在設(shè)定好一個(gè)唯一鍵的 Map 數(shù)據(jù)類型后,再用其自帶的 Map.prototype.keys() 方法取到相應(yīng)的鍵類數(shù)組,最后將類數(shù)組進(jìn)行一次轉(zhuǎn)化即可

function uniq(arr) {
 ? ?let map = new Map();
 ? ?for (let i = 0; i < arr.length; i++) {
 ? ? ? ?!map.has(arr[i]) && map.set(arr[i], true);
 ?  }
 ? ?return [...map.keys()];
}
// 運(yùn)行結(jié)果
// [1, "1", "a", {}, {}, { a: 1 }, {}, { a: 1 }, [], [], [1], undefined, null, NaN];
// 與 lodash 結(jié)果相同
  • Set

與 Map 類似,但是它里面每一項(xiàng)的值是唯一的,沒(méi)有重復(fù)的值,Set是一個(gè)構(gòu)造函數(shù),用來(lái)生成set的數(shù)據(jù)結(jié)構(gòu)。運(yùn)用數(shù)據(jù)類型的特性完成去重,這個(gè)方法也是最熱門的方法

function uniq(arr) {
 ? ?return [...new Set(arr)];
}
// 運(yùn)行結(jié)果
// [1, "1", "a", {}, {}, { a: 1 }, {}, { a: 1 }, [], [], [1], undefined, null, NaN];
// 與 lodash 結(jié)果相同

原型鏈

基于原型對(duì)象的繼承使得不同構(gòu)造函數(shù)的原型對(duì)象關(guān)聯(lián)在一起,并且這種關(guān)聯(lián)的關(guān)系是一種鏈狀的結(jié)構(gòu),我們將原型對(duì)象的鏈狀結(jié)構(gòu)關(guān)系稱為原型鏈。

簡(jiǎn)單地說(shuō):原型鏈就是查找規(guī)則,__proto__對(duì)象原型的意義就在于為對(duì)象成員查找機(jī)制提供一個(gè)方向,或者說(shuō)一條路線。

call、bind、apply的含義和區(qū)別

  • 區(qū)別 : 傳參不一樣

call()

  • 改變this指向

  • 可以調(diào)用函數(shù)

  • 參數(shù): 接受的是若干個(gè)參數(shù)的列表 call(this,1,2,3)

apply()

  • 改變this指向

  • 可以調(diào)用函數(shù)

  • 參數(shù): 參數(shù)的數(shù)組 apply(this,[1,2,3])

bind()

  • 只改變this指向,不調(diào)用函數(shù),比如用來(lái)改變定時(shí)器內(nèi)部的this指向

Class

  1. class本質(zhì)還是function

  2. 類的所有方法都定義在類的 prototype屬性上

  3. 類創(chuàng)建的實(shí)例 里面也有 __ proto __ 指向類的 prototype 原型對(duì)象

  4. 所以 ES6 的類 他的絕大部分功能 es5 都可以做到 新的 calss 寫法 只是讓對(duì)象原型的寫法 更加清晰 更像面向?qū)ο缶幊痰恼Z(yǔ)法而已

  5. 所以 ES6 的類 其實(shí)就是語(yǔ)法糖

Class和構(gòu)造函數(shù)的區(qū)別

  1. 類的內(nèi)部所有定義的方法,都是不可枚舉的(但是在es5中prototype的方法是可以進(jìn)行枚舉的)

  2. 類的構(gòu)造函數(shù),不使用new是沒(méi)法調(diào)用的,會(huì)報(bào)錯(cuò)。這是它跟普通構(gòu)造函數(shù)的一個(gè)主要區(qū)別,后者可以直接調(diào)用

  3. Class不存在變量提升(hoist),這一點(diǎn)與ES5完全不同

  4. ES5的繼承,實(shí)質(zhì)是先創(chuàng)造子類的實(shí)例對(duì)象this,然后再將父類的方法添加到this上面(Parent.apply(this))。ES6的繼承機(jī)制完全不同,實(shí)質(zhì)是先創(chuàng)造父類的實(shí)例對(duì)象this(所以必須先調(diào)用super方法),然后再用子類的構(gòu)造函數(shù)修改this。

js繼承的幾種方式及其優(yōu)缺點(diǎn)

原型鏈繼承

function Parent() {
 ?this.name = 'kevin';
}
?
Parent.prototype.getName = function () {
 ?console.log(this.name);
}
?
function Child() {
?
}
?
Child.prototype = new Parent();
Child.prototype.constructor = Child;
?
var child1 = new Child();
console.log(child1.getName()) // kevin

缺點(diǎn):

  1. 在創(chuàng)建 Child 的實(shí)例時(shí),不能向Parent傳參

  2. 引用類型的屬性被所有實(shí)例共享

借用構(gòu)造函數(shù)繼承

function Parent() {
 ?this.names = ['kevin', 'daisy'];
}
?
function Child() {
 ?Parent.call(this);
}
?
var child1 = new Child();
child1.names.push('yayu');
console.log(child1.names); // ["kevin", "daisy", "yayu"]
?
var child2 = new Child();
console.log(child2.names); // ["kevin", "daisy"]

優(yōu)點(diǎn):

  1. 可以在 Child 中向 Parent 傳參

  2. 避免了引用類型的屬性被所有實(shí)例共享

缺點(diǎn):

  • 只能繼承父類的實(shí)例屬性和方法,不能繼承原型屬性/方法

  • 無(wú)法實(shí)現(xiàn)復(fù)用,每個(gè)子類都有父類實(shí)例函數(shù)的副本,影響性能

function Parent(name) {
 ?this.name = name;
 ?this.colors = ['red', 'blue', 'green'];
}
?
Parent.prototype.getName = function () {
 ?console.log(this.name)
}
?
function Child(name, age) {
 ?Parent.call(this, name);
 ?this.age = age;
}
?
Child.prototype = new Parent();
Child.prototype.constructor = Child;
?
var child1 = new Child('kevin', '18');
child1.colors.push('black');
?
console.log(child1.name); // kevin
console.log(child1.age); // 18
console.log(child1.colors); // ["red", "blue", "green", "black"]
?
var child2 = new Child('daisy', '20');
console.log(child2.name); // daisy
console.log(child2.age); // 20
console.log(child2.colors); // ["red", "blue", "green"]

缺點(diǎn):

構(gòu)建原型鏈的時(shí)候,Child.prototype的原型上面會(huì)有name、colors兩個(gè)屬性;在創(chuàng)建child1的時(shí)候它的實(shí)例上也會(huì)有name、colors。實(shí)例對(duì)象child1上的兩個(gè)屬性就屏蔽了其原型對(duì)象Child.prototype的兩個(gè)同名屬性。

所以,組合模式的缺點(diǎn)就是在使用子類創(chuàng)建實(shí)例對(duì)象時(shí),會(huì)調(diào)用兩次父構(gòu)造函數(shù),其原型鏈中會(huì)存在兩份相同的屬性/方法。

原型式繼承

略。不重要可不說(shuō)

寄生式繼承

略。不重要可不說(shuō)

寄生組合式繼承?

對(duì)于組合式繼承的缺點(diǎn),思考一下,如何不調(diào)用兩次父構(gòu)造函數(shù),不使用 Child.prototype = new Parent() ,而是間接的讓 Child.prototype 訪問(wèn)到 Parent.prototype 呢?

function Parent(name) {
 ?this.name = name;
 ?this.colors = ['red', 'blue', 'green'];
}
?
Parent.prototype.getName = function () {
 ?console.log(this.name)
}
?
function Child(name, age) {
 ?Parent.call(this, name);
 ?this.age = age;
}
?
// 關(guān)鍵的三步
var F = function () {};
F.prototype = Parent.prototype;
// Child.prototype = new F();
let f = new F()
f.constructor = Child
Child.prototype = f
?
?
?
var child1 = new Child('kevin', '18');
console.log(child1);

最后我們把第三步的方法封裝一下

function object(o) {
 ?function F() {}
 ?F.prototype = o;
 ?return new F();
}
?
function prototype(child, parent) {
 ?var prototype = object(parent.prototype);
 ?prototype.constructor = child;
 ?child.prototype = prototype;
}
?
// 當(dāng)我們使用的時(shí)候:
prototype(Child, Parent);

這種方式的高效率體現(xiàn)它只調(diào)用了一次 Parent 構(gòu)造函數(shù),并且因此避免了在 Parent.prototype 上面創(chuàng)建不必要的、多余的屬性。與此同時(shí),原型鏈還能保持不變;因此,還能夠正常使用 instanceof 和 isPrototypeOf。開發(fā)人員普遍認(rèn)為寄生組合式繼承是引用類型最理想的繼承范式。

ES6類繼承extends?

ES6繼承的原理跟寄生組合式繼承是一樣的。

閉包

定義

  • 閉包就是能夠讀取其他函數(shù)內(nèi)部變量的函數(shù)。例如在javascript中,只有函數(shù)內(nèi)部的子函數(shù)才能讀取局部變量,所以閉包可以理解成定義在一個(gè)函數(shù)內(nèi)部的函數(shù)。在本質(zhì)上,閉包就是將函數(shù)內(nèi)部和函數(shù)外部連接起來(lái)的橋梁。

優(yōu)缺點(diǎn):

  • 能夠訪問(wèn)局部變量

  • 保護(hù)局部變量

  • 由于閉包會(huì)將它的外部函數(shù)的作用域也保存在內(nèi)存中,因此會(huì)比其他函數(shù)更占用內(nèi)存,這樣的話,如果過(guò)度使用閉包,就會(huì)有內(nèi)存泄露的威脅。解決方法——使用完變量后,手動(dòng)將它賦值為null。

應(yīng)用:

  • 構(gòu)造函數(shù)的私有屬性。由于javascript中天然沒(méi)有類的實(shí)現(xiàn),某些不希望被外部修改的私有屬性可以通過(guò)閉包的方式實(shí)現(xiàn)

  • 函數(shù)防抖、節(jié)流

瀏覽器的緩存機(jī)制

瀏覽器與服務(wù)器通信的方式為應(yīng)答模式,即是:瀏覽器發(fā)起HTTP請(qǐng)求 – 服務(wù)器響應(yīng)該請(qǐng)求。

  • 瀏覽器每次發(fā)起請(qǐng)求,都會(huì)先在瀏覽器緩存中查找該請(qǐng)求的結(jié)果以及緩存標(biāo)識(shí)

  • 瀏覽器每次拿到返回的請(qǐng)求結(jié)果都會(huì)將該結(jié)果和緩存標(biāo)識(shí)存入瀏覽器緩存中

根據(jù)是否需要向服務(wù)器重新發(fā)起HTTP請(qǐng)求將緩存過(guò)程分為兩個(gè)部分,分別是強(qiáng)制緩存和協(xié)商緩存。

  • 強(qiáng)制緩存就是向?yàn)g覽器緩存查找該請(qǐng)求結(jié)果,并根據(jù)該結(jié)果的緩存規(guī)則來(lái)決定是否使用該緩存結(jié)果的過(guò)程

  • 協(xié)商緩存就是強(qiáng)制緩存失效后,瀏覽器攜帶緩存標(biāo)識(shí)向服務(wù)器發(fā)起請(qǐng)求,由服務(wù)器根據(jù)緩存標(biāo)識(shí)決定是否使用緩存的過(guò)程

強(qiáng)制緩存優(yōu)先于協(xié)商緩存進(jìn)行,若強(qiáng)制緩存(Expires和Cache-Control)生效則直接使用緩存,若不生效則進(jìn)行協(xié)商緩存,協(xié)商緩存由服務(wù)器決定是否使用緩存,若協(xié)商緩存失效,那么代表該請(qǐng)求的緩存失效,重新獲取請(qǐng)求結(jié)果,再存入瀏覽器緩存中;生效則返回304,繼續(xù)使用緩存。

任務(wù)隊(duì)列(宏/微任務(wù))

首先我們需要明白以下幾件事情:

  • JS分為同步任務(wù)和異步任務(wù)

  • 同步任務(wù)都在主線程上執(zhí)行,形成一個(gè)執(zhí)行棧

  • 所謂 "異步",簡(jiǎn)單說(shuō)就是一個(gè)任務(wù)不是連續(xù)完成的,先執(zhí)行第一段,等做好了準(zhǔn)備,再回過(guò)頭執(zhí)行第二段,第二段也被叫做回調(diào);同步則是連貫完成的。

  • 主線程之外,有一個(gè)任務(wù)隊(duì)列,只要異步任務(wù)有了運(yùn)行結(jié)果,就在任務(wù)隊(duì)列之中放置一個(gè)事件。

  • 一旦執(zhí)行棧中的所有同步任務(wù)執(zhí)行完畢(此時(shí)JS引擎空閑),系統(tǒng)就會(huì)讀取任務(wù)隊(duì)列,將可運(yùn)行的異步任務(wù)添加到可執(zhí)行棧中,開始執(zhí)行。

宏任務(wù)

可以理解是每次執(zhí)行棧執(zhí)行的代碼就是一個(gè)宏任務(wù)(包括每次從事件隊(duì)列中獲取一個(gè)事件回調(diào)并放到執(zhí)行棧中執(zhí)行)。

主要包含:script(整體代碼)、setTimeout、setInterval、DOM事件

微任務(wù)

可以理解是在當(dāng)前(主線程)任務(wù)執(zhí)行結(jié)束后立即執(zhí)行的任務(wù)。也就是說(shuō),在當(dāng)前任務(wù)任務(wù)后,下一個(gè)任務(wù)之前,在渲染之前。

所以它的響應(yīng)速度相比setTimeout(setTimeout是task)會(huì)更快,因?yàn)闊o(wú)需等渲染。也就是說(shuō),在某一個(gè)macrotask執(zhí)行完后,就會(huì)將在它執(zhí)行期間產(chǎn)生的所有microtask都執(zhí)行完畢(在渲染前)。

主要包含:Promise.then

運(yùn)行機(jī)制(時(shí)間循環(huán))

在事件循環(huán)中,每進(jìn)行一次循環(huán)操作稱為 tick,每一次 tick 的任務(wù)處理模型是比較復(fù)雜的,但關(guān)鍵步驟如下:

  • 執(zhí)行一個(gè)宏任務(wù)(全局Script腳本)

  • 產(chǎn)生的的宏任務(wù)和微任務(wù)進(jìn)入各自的隊(duì)列中

  • 宏任務(wù)執(zhí)行完畢后,立即執(zhí)行當(dāng)前微任務(wù)隊(duì)列中的所有微任務(wù)(依次執(zhí)行)

  • 當(dāng)前宏任務(wù)執(zhí)行完畢,開始檢查渲染,然后GUI線程接管渲染

  • 渲染完畢后,JS線程繼續(xù)接管,開始下一個(gè)宏任務(wù)(從事件隊(duì)列中獲?。?/p>

事件委托

利用事件冒泡的原理,將原本綁定給子元素的事件,綁定給父元素,子元素觸發(fā)的事件冒泡給父元素,讓父元素觸發(fā)事件,執(zhí)行函數(shù)。

事件委托好處:1. 效率好;2. 對(duì)于新增的子元素事件依然生效

請(qǐng)求

請(qǐng)求的方式有哪些,應(yīng)用場(chǎng)景是什么

  • GET

GET請(qǐng)求是向服務(wù)端請(qǐng)求獲取某個(gè)或某些資源(resource),比如查詢數(shù)據(jù)庫(kù)單個(gè)或list數(shù)據(jù),服務(wù)端成功的話,一般狀態(tài)碼返回200。

  • POST

POST請(qǐng)求是用來(lái)向服務(wù)端請(qǐng)求新增資源(resource),處理成功的話,服務(wù)端一般返回狀態(tài)碼201。

  • PUT

PUT請(qǐng)求一般是用來(lái)向服務(wù)端請(qǐng)求修改某個(gè)已存在的資源(resource),服務(wù)端一般返回狀態(tài)碼200,204等。

  • DELETE

DELETE請(qǐng)求一般是用來(lái)向服務(wù)端請(qǐng)求刪除某個(gè)已存在的資源(resource),服務(wù)端一般返回200,202等。

  • PATCH

PATCH請(qǐng)求一般是對(duì)某個(gè)資源做局部修改,如個(gè)別字段

什么是promise,解決了什么問(wèn)題

Promise

Promise 是異步編程的一種解決方案:從語(yǔ)法上講,promise是一個(gè)對(duì)象,從它可以獲取異步操作的消息

  • promise有三種狀態(tài): pending(等待態(tài)),fulfiled(成功態(tài)),rejected(失敗態(tài));

    • 狀態(tài)一旦改變,就不會(huì)再變。創(chuàng)造promise實(shí)例后,它會(huì)立即執(zhí)行。

  • resolve reject都是函數(shù), resolve用來(lái)處理成功的狀態(tài),reject用來(lái)處理失敗的狀態(tài)

  • 如何訪問(wèn)promise實(shí)例中的數(shù)據(jù)

    • promise提供了兩個(gè)方法 .then()處理成功 .catch()處理失敗(不會(huì)同時(shí)存在2中狀態(tài))

promise基本概念

  1. Promise 是一個(gè)構(gòu)造函數(shù)

  2. promise.prototype上包含一個(gè) .then 方法

  3. .then()方法 可以用來(lái)預(yù)先指定失敗的回調(diào)函數(shù)

  • p.then(成功的回調(diào)函數(shù) ,失敗的回調(diào)函數(shù)) p.then(result=>{},error=>{})

  • 調(diào)用p.then()方法時(shí),成功的函數(shù)是必選的 失敗的回調(diào)函數(shù)是可選的

談?wù)剬?duì)async/await的理解

async和await

  • await必須結(jié)合async使用,async通常不會(huì)單獨(dú)使用

  • async表示這個(gè)函數(shù)是一個(gè)異步函數(shù),它的返回值如果是一個(gè)普通數(shù)據(jù)類型,默認(rèn)會(huì)用Promise將數(shù)據(jù)包裹

  • await 等待?等待什么?等待的是一個(gè)異步的結(jié)果

  • 異步和同步從上往下的順序執(zhí)行

相對(duì)于promise的優(yōu)點(diǎn):

  • 解決了地獄回調(diào)問(wèn)題

  • 更簡(jiǎn)潔 更容易調(diào)試 有更好的錯(cuò)誤處理 有條件分支處理

  • 處理中間值更簡(jiǎn)單 更清楚異常堆棧來(lái)自哪里

跨越問(wèn)題如何解決

  • 同源:2個(gè)頁(yè)面的協(xié)議/域名/端口均相同為同源

  • 同源策略 :A網(wǎng)站的js不允許和非同源的網(wǎng)站進(jìn)行資源交互

  • 跨域 :協(xié)議/域名/端口不一致時(shí)(會(huì)被瀏覽器攔截)

  • 解決方案

  • JSONP 和 CORS和代理服務(wù)器

  • CORS:出現(xiàn)的較晚,它是 W3C 標(biāo)準(zhǔn),屬于跨域 Ajax 請(qǐng)求的根本解決方案。支持 GET 和 POST 請(qǐng)求。缺點(diǎn)是不兼容某些低版本的瀏覽器

    • 原理: 設(shè)置允許的響應(yīng)頭(需要瀏覽器和服務(wù)器同時(shí)支持).后臺(tái)里面設(shè)置

  • JSONP:出現(xiàn)的早,兼容性好(兼容低版本IE)。是前端程序員為了解決跨域問(wèn)題,被迫想出來(lái)的一種臨時(shí)解決方案。

    • 原理:根據(jù)< script>標(biāo)簽的src屬性不受瀏覽器同源策略的限制

    • 動(dòng)態(tài)創(chuàng)建< script>標(biāo)簽,結(jié)合它的src屬性傳遞可查詢參數(shù)

      • 參數(shù)的值是一個(gè)函數(shù)名(函數(shù)名最好隨機(jī)生成,防止變量污染)

    • 服務(wù)器返回的是一段函數(shù)執(zhí)行代碼

    缺點(diǎn)是只支持 GET 請(qǐng)求,不支持 POST 請(qǐng)求。

    • 實(shí)現(xiàn)過(guò)程:

    • script標(biāo)簽里的src屬性動(dòng)態(tài)創(chuàng)建和移除

    • 在Jsonp請(qǐng)求時(shí),動(dòng)態(tài)向<head>中append(添加)一個(gè)<script>標(biāo)簽

    • 在Jsonp請(qǐng)求成功后,動(dòng)態(tài)從<head>中移除剛才append的<script>標(biāo)簽

    由于瀏覽器同源策略的限制,網(wǎng)頁(yè)中無(wú)法通過(guò) Ajax 請(qǐng)求非同源的接口數(shù)據(jù)。但是 <script> 標(biāo)簽不受瀏覽器同
    源策略的影響,可以通過(guò) src 屬性,請(qǐng)求非同源的 js 腳本。
    因此,JSONP 的實(shí)現(xiàn)原理,就是通過(guò) <script> 標(biāo)簽的 src 屬性,請(qǐng)求跨域的數(shù)據(jù)接口,并通過(guò)函數(shù)調(diào)用的形式,
    接收跨域接口響應(yīng)回來(lái)的數(shù)據(jù)
  • 代理服務(wù)器

    • 原理: 服務(wù)器和服務(wù)器之前發(fā)送請(qǐng)求不受瀏覽器同源策略的影響

      • 在vue.config.js 文件中配置

輸入網(wǎng)站url地址后發(fā)生了什么

  • URL 解析

  • DNS解析,尋找服務(wù)器(DNS (Domain Name System) 是一個(gè)協(xié)議,主要用途是將一個(gè)域名解析成 IP 地址,這個(gè)過(guò)程叫做域名解析 (Name resolution))

  • TCP連接(傳輸控制協(xié)議(TCP,Transmission Control Protocol)),三次握手

    • 第一次:瀏覽器向服務(wù)器發(fā)送請(qǐng)求(SYN=1),等待服務(wù)器確認(rèn);

    • 第二次:服務(wù)器收到請(qǐng)求并確認(rèn),回復(fù)一個(gè)指令(SYN=1,ACK=1);

    • 第三次:客戶端收到服務(wù)器的回復(fù)指令,并返回確認(rèn)(ACK=1);

  • 發(fā)送http請(qǐng)求,找到相應(yīng)的資源庫(kù)

  • 返回http響應(yīng)(返回?cái)?shù)據(jù))

  • 瀏覽器解析渲染頁(yè)面

  • 斷開連接

ajax工作流程及原理

  • Ajax的應(yīng)用的五個(gè)步驟

    1、建立XMLHttpRequest對(duì)象;

    2、設(shè)置回調(diào)函數(shù);

    3、使用open方法與服務(wù)器建立連接;

    4、向服務(wù)器端發(fā)送數(shù)據(jù);

    5、在回調(diào)函數(shù)針對(duì)不同響應(yīng)狀態(tài)進(jìn)行處理;

  • 原理

    ajax的工作原理就是通過(guò)XmlHttpRequest對(duì)象來(lái)向服務(wù)器發(fā)出異步請(qǐng)求,從服務(wù)器中獲得數(shù)據(jù),然后用Javascript來(lái)操作DOM從而更新局部頁(yè)面

axios 是什么、怎么使用

axios 是一個(gè)基于Promise 用于瀏覽器和 nodejs 的 HTTP 客戶端,它本身具有以下特征:

  • Ajax 是頁(yè)面無(wú)刷新請(qǐng)求數(shù)據(jù)操作

  1. 從瀏覽器中創(chuàng)建 XMLHttpRequest

  2. 從 node.js 發(fā)出 http 請(qǐng)求

  3. 支持 Promise API

  4. 攔截請(qǐng)求和響應(yīng)

  5. 轉(zhuǎn)換請(qǐng)求和響應(yīng)數(shù)據(jù)

  6. 取消請(qǐng)求

  7. 自動(dòng)轉(zhuǎn)換JSON數(shù)據(jù)

  8. 客戶端支持防止 CSRF/XSRF

Localstorage、sessionStorage、cookie 的區(qū)別

共同點(diǎn):都是保存在瀏覽器端、且同源的

區(qū)別:

  • 請(qǐng)求不同

    • cookie 數(shù)據(jù)始終在同源的 http 請(qǐng)求中攜帶(即使不需要)

    • sessionStorage 和 localStorage不會(huì)自動(dòng)把數(shù)據(jù)發(fā)送給服務(wù)器,僅在本地保存

  • 存儲(chǔ)大小限制不同

    • cookie 數(shù)據(jù)不能超過(guò) 4K(只適合保存很小的數(shù)據(jù),如會(huì)話標(biāo)識(shí))

    • localStorage和sessionStorage 達(dá)到 5M

  • 數(shù)據(jù)有效期不同

    • cookie只在設(shè)置的cookie 過(guò)期時(shí)間之前有效,即使窗口關(guān)閉或?yàn)g覽器關(guān)閉

    • localStorage: 始終有效,窗口或?yàn)g覽器關(guān)閉也一直保存,因此用作持久數(shù)據(jù)

    • sessionStorage : 僅在當(dāng)前瀏覽器窗口關(guān)閉之前有效

  • 作用域不同

    • cookie: 所有同源窗口中都是共享的

    • localStorage: 在所有同源窗口中都是共享的

    • sessionStorage不在不同的瀏覽器窗口中共享,即使是同一個(gè)頁(yè)面

  • 安全性問(wèn)題

    • 如果 cookie 被人攔截了,那人就可以取得所有的 session 信息。即使加密也與事無(wú)補(bǔ),因?yàn)閿r截者并不需要知道 cookie 的意義,他只要原樣轉(zhuǎn)發(fā) cookie 就可以達(dá)到目的了

后端接口沒(méi)寫出來(lái),前端如何進(jìn)行開發(fā)

  • mock(模擬接口返回的信息)

  • 單純的前端mock可以通過(guò)抓包工具Fiddler,Charles實(shí)現(xiàn)

  • 通過(guò)修改代理返回的數(shù)據(jù),實(shí)現(xiàn)多種場(chǎng)景的測(cè)試。這里在抓包工具之中會(huì)解釋

post請(qǐng)求和get請(qǐng)求的區(qū)別

  • get 傳送的數(shù)據(jù)長(zhǎng)度有限制,post 沒(méi)有

  • get 通過(guò) url 傳遞(查詢字符串),在瀏覽器地址欄可見,post 是在請(qǐng)求中傳遞

  • 適用場(chǎng)景

    • post 一般用于表單提交

    • get 一般用于簡(jiǎn)單的數(shù)據(jù)查詢,嚴(yán)格要求不是那么高的場(chǎng)景

Session,Token,Cookie在身份認(rèn)證方面的區(qū)別

  • 為什么要使用身份認(rèn)證:

    • 因?yàn)閔ttp協(xié)議是無(wú)狀態(tài)性的,每一次http請(qǐng)求都是獨(dú)立的

    • 連續(xù)多個(gè)請(qǐng)求之間無(wú)直接關(guān)系,服務(wù)器不會(huì)主動(dòng)保存每次http請(qǐng)求狀態(tài)

  • Session

    • session數(shù)據(jù)放在服務(wù)器上。

    • session會(huì)在一定時(shí)間內(nèi)保存在服務(wù)器上。當(dāng)訪問(wèn)增多,會(huì)比較占用你服務(wù)器的性能

    • 將登陸信息等重要信息存放為session

  • Cookie

    • cookie數(shù)據(jù)存放在客戶端上(所以安全性不高)

    • 所以每個(gè)域的cookie數(shù)量是有限的(比較小4kb)

    • 每次發(fā)送請(qǐng)求會(huì)自動(dòng)攜帶Cookie

  • Token

    • token是服務(wù)端生成用于驗(yàn)證用戶登錄狀態(tài)的加密數(shù)據(jù),和session驗(yàn)證差不多。

    • token驗(yàn)證服務(wù)端不需要存儲(chǔ)用戶會(huì)話的配置數(shù)據(jù),只是加密的字符串

    • 然后用Token設(shè)置請(qǐng)求頭

    • Token的目的是為了減輕服務(wù)器的壓力,減少頻繁的查詢數(shù)據(jù)庫(kù)

常見的狀態(tài)碼

  • 200:請(qǐng)求已成功

  • 401:沒(méi)有權(quán)限

  • 402: 參數(shù)傳遞錯(cuò)誤

  • 403:服務(wù)器已經(jīng)理解請(qǐng)求,但是拒絕執(zhí)行它。

  • 404:請(qǐng)求失敗,請(qǐng)求所希望得到的資源未被在服務(wù)器上發(fā)現(xiàn)。(未找到頁(yè)面)

  • 500:服務(wù)器遇到了一個(gè)未曾預(yù)料的狀況,導(dǎo)致了它無(wú)法完成對(duì)請(qǐng)求的處理。一般來(lái)說(shuō),這個(gè)問(wèn)題都會(huì)在服務(wù)器端的源代碼出現(xiàn)錯(cuò)誤時(shí)出現(xiàn)。

Vue2

Vue是什么

是一個(gè)用于創(chuàng)建用戶界面的開源JavaScript框架,也是一個(gè)創(chuàng)建單頁(yè)應(yīng)用的Web應(yīng)用框架。

它的核心特征是數(shù)據(jù)驅(qū)動(dòng)(MVVM)

MVVM

MVVM表示的是Model-View-ViewModel

  • Model:模型層,負(fù)責(zé)處理業(yè)務(wù)邏輯以及和服務(wù)器端進(jìn)行交互

  • View:視圖層:負(fù)責(zé)將數(shù)據(jù)模型轉(zhuǎn)化為UI展示出來(lái),可以簡(jiǎn)單的理解為HTML頁(yè)面

  • ViewModel:視圖模型層,用來(lái)連接Model和View,是Model和View之間的通信橋梁

MVVM就是一種結(jié)構(gòu)設(shè)計(jì)模式。

  1. 什么是設(shè)計(jì)模式 : 設(shè)計(jì)模式,是對(duì)軟件設(shè)計(jì)中普遍存在的各種問(wèn)題所提出的解決方案

  2. mvvm的好處 : 減少DOM操作,提高開發(fā)效率

  3. MVVM設(shè)計(jì)模式 : M-model(數(shù)據(jù)模型) V-View(視圖VM-viewmodel(連接數(shù)據(jù)模型和視圖的對(duì)象,它可以監(jiān)聽數(shù)據(jù)的變化,將數(shù)據(jù)變化映射到視圖,反過(guò)來(lái)也成立

觀察者模式和發(fā)布訂閱者模式

1、觀察者模式優(yōu)缺點(diǎn)

優(yōu)點(diǎn):模式簡(jiǎn)單,雙方直接通信。

缺點(diǎn):

  • 如果一個(gè)被觀察者對(duì)象有很多的直接和間接的觀察者的話,將所有的觀察者都通知到會(huì)花費(fèi)很多時(shí)間。

  • 雖然觀察者模式可以隨時(shí)使觀察者知道所觀察的對(duì)象發(fā)生了變化,但是觀察者模式?jīng)]有相應(yīng)的機(jī)制使觀察者知道所觀察的對(duì)象是怎么發(fā)生變化的。

2、發(fā)布訂閱者模式優(yōu)缺點(diǎn)

優(yōu)點(diǎn):

完全解耦特性:消息的發(fā)布者和消息的訂閱者在開發(fā)的時(shí)候完全不需要事先知道對(duì)方的存在,可以獨(dú)立地進(jìn)行開發(fā)。

訂閱者可以只訂閱自己想要的消息

缺點(diǎn):發(fā)布訂閱模式的缺點(diǎn)正是來(lái)源于它的優(yōu)點(diǎn)。通過(guò)從訂閱者中解耦發(fā)布者,它有時(shí)會(huì)很難保證應(yīng)用程序的特定部分按照我們期望的運(yùn)行。倘若我們假設(shè)訂閱者需要記錄或輸出一些與應(yīng)用程序處理有關(guān)的錯(cuò)誤。如果訂閱者執(zhí)行日志崩潰了(或處于某種原因無(wú)法正常運(yùn)行),由于系統(tǒng)的解耦特性,發(fā)布者就不會(huì)看到這一點(diǎn)。

SPA(單頁(yè)應(yīng)用)的理解

single-page application,它通過(guò)動(dòng)態(tài)重寫當(dāng)前頁(yè)面來(lái)與用戶交互,整個(gè)運(yùn)用一個(gè)頁(yè)面。

單頁(yè)面應(yīng)用(SPA) 多頁(yè)面應(yīng)用(MPA)
組成 一個(gè)主頁(yè)面和多個(gè)頁(yè)面片段 多個(gè)主頁(yè)面
刷新方式 局部刷新 整頁(yè)刷新
url模式 哈希模式 歷史模式
SEO搜索引擎優(yōu)化 難實(shí)現(xiàn),可使用SSR方式改善 容易實(shí)現(xiàn)
數(shù)據(jù)傳遞 容易 通過(guò)url、cookie、localStorage等傳遞
頁(yè)面切換 速度快,用戶體驗(yàn)良好 切換加載資源,速度慢,用戶體驗(yàn)差
維護(hù)成本 相對(duì)容易 相對(duì)復(fù)雜

單頁(yè)應(yīng)用優(yōu)缺點(diǎn)

優(yōu)點(diǎn):

  • 具有桌面應(yīng)用的即時(shí)性、網(wǎng)站的可移植性和可訪問(wèn)性

  • 用戶體驗(yàn)好、快,內(nèi)容的改變不需要重新加載整個(gè)頁(yè)面

  • 良好的前后端分離,分工更明確

缺點(diǎn):

  • 不利于搜索引擎的抓取

  • 首次渲染速度相對(duì)較慢

響應(yīng)式原理

vue.js 是采用數(shù)據(jù)劫持結(jié)合發(fā)布者-訂閱者模式的方式,通過(guò)Object.defineProperty()來(lái)劫持各個(gè)屬性的setter, getter,在數(shù)據(jù)變動(dòng)時(shí)發(fā)布消息給訂閱者,觸發(fā)相應(yīng)的監(jiān)聽回調(diào)。

具體步驟:

第一步:需要 observe 的數(shù)據(jù)對(duì)象進(jìn)行遞歸遍歷,包括子屬性對(duì)象的屬性,都加上 setter 和 getter 這樣的話。給這個(gè)對(duì)象的某個(gè)值賦值,就會(huì)觸發(fā)setter,那么就能監(jiān)聽到了數(shù)據(jù)變化。

第二步:compile解析模板指令,將模板中的變量替換成數(shù)據(jù),然后初始化渲染頁(yè)面視圖,并將每個(gè)指令對(duì)應(yīng)的節(jié)點(diǎn)綁定更新函數(shù),添加監(jiān)聽數(shù)據(jù)的訂閱者,一旦數(shù)據(jù)有變動(dòng),收到通知,更新視圖

第三步:Watcher訂閱者是Observer和Compile之間通信的橋梁,主要做的事情是: 1、在自身實(shí)例化時(shí)往屬性訂閱器(dep)里面添加自己 2、自身必須有一個(gè)update()方法 3、待屬性變動(dòng)dep.notice()通知時(shí),能調(diào)用自身的 update()方法,并觸發(fā)Compile中綁定的回調(diào),則功成身退。

第四步:MVVM作為數(shù)據(jù)綁定的入口,整合Observer、Compile和Watcher三者,通過(guò)Observer來(lái)監(jiān)聽自己的 model數(shù)據(jù)變化,通過(guò)Compile來(lái)解析編譯模板指令,最終利用Watcher搭起Observer和Compile之間的通信橋梁達(dá)到數(shù)據(jù)變化.> 視圖更新:視圖交互變化(input)-> 數(shù)據(jù)model變更的雙向綁定效果.

Vue2生命周期

Vue生命周期總共可以分為8個(gè)階段:創(chuàng)建前后, 載入前后,更新前后,銷毀前銷毀后,以及一些特殊場(chǎng)景的生命周期

生命周期 描述
beforeCreate 組件實(shí)例被創(chuàng)建之初(初始化vue實(shí)例,進(jìn)行數(shù)據(jù)觀測(cè))
created 組件實(shí)例已經(jīng)完全創(chuàng)建(完成數(shù)據(jù)觀測(cè),屬性與方法的運(yùn)算,watch、event事件回調(diào)的配置)
beforeMount 組件掛載之前(處理vm.el)
mounted 組件掛載到實(shí)例上去之后(掛載el變成dom)
beforeUpdate 組件數(shù)據(jù)發(fā)生變化,更新之前
updated 組件數(shù)據(jù)更新之后
beforeDestroy 組件實(shí)例銷毀之前
destroyed 組件實(shí)例銷毀之后
activated keep-alive 緩存的組件激活時(shí)
deactivated keep-alive 緩存的組件停用時(shí)調(diào)用
errorCaptured 捕獲一個(gè)來(lái)自子孫組件的錯(cuò)誤時(shí)被調(diào)用

data為什么是函數(shù)的存在

  • 產(chǎn)生塊級(jí)作用域--->防止變量污染

  • 讓各個(gè)組件實(shí)例維護(hù)各自的數(shù)據(jù)

  • 如果單純的寫成對(duì)象形式

    • 就使得所有組件實(shí)例共用了一份 data

    • 就會(huì)造成一個(gè)變了全都會(huì)變的結(jié)果

Vue組件通信的方式

  1. 通過(guò) props 傳遞

  2. 通過(guò) $emit 觸發(fā)自定義事件

  3. 使用 ref

  4. EventBus

  5. $parent 或$root

  6. attrs 與 listeners

  7. Provide 與 Inject

  8. Vuex

  9. vue2.6新增的Vue.observable。一個(gè)小型的狀態(tài)管理器

keep-alive原理及緩存策略

  • Vue.js內(nèi)部在creatd鉤子里將DOM節(jié)點(diǎn)抽象成了一個(gè)個(gè)的VNode節(jié)點(diǎn),keep-alive組件的緩存也是基于VNode節(jié)點(diǎn)的而不是直接存儲(chǔ)DOM結(jié)構(gòu)。

  • 它將滿足條件(pruneCache與pruneCache)的組件在cache對(duì)象中緩存起來(lái),在需要重新渲染的時(shí)候再將vnode節(jié)點(diǎn)從cache對(duì)象中取出并渲染。

  • destroyed鉤子則在組件被銷毀的時(shí)候清除cache緩存中的所有組件實(shí)例。

思考題:緩存后如何獲取數(shù)據(jù)?

  • beforeRouteEnter

  • actived

computed原理

computed 也是響應(yīng)式的,給 computed 設(shè)置的 get 和 set 函數(shù),會(huì)跟 Object.defineProperty 關(guān)聯(lián)起來(lái)。所以 Vue 能捕捉到 讀取computed 和 賦值computed 的操作。

計(jì)算屬性是基于它們的依賴進(jìn)行緩存的。計(jì)算屬性只有在它的相關(guān)依賴發(fā)生改變時(shí)才會(huì)重新求值。

首先 computed 計(jì)算后,會(huì)把計(jì)算得到的值保存到一個(gè)變量中。讀取 computed 時(shí)便直接返回這個(gè)變量。當(dāng)使用緩存時(shí),就直接返回這個(gè)變量。當(dāng) computed 更新時(shí),就會(huì)重新賦值更新這個(gè)變量。

computed 控制緩存的重要一點(diǎn)是 【臟數(shù)據(jù)標(biāo)志位 dirty】,dirty 是 watcher 的一個(gè)屬性

當(dāng) dirty 為 true 時(shí),讀取 computed 會(huì)重新計(jì)算

當(dāng) dirty 為 false 時(shí),讀取 computed 會(huì)使用緩存

1一開始每個(gè) computed 新建自己的watcher時(shí),會(huì)設(shè)置 watcher.dirty = true,以便于computed 被使用時(shí),會(huì)計(jì)算得到值

2當(dāng) 依賴的數(shù)據(jù)變化了,通知 computed 時(shí),會(huì)設(shè)置 watcher.dirty = true,以便于其他地方重新渲染,從而重新讀取 computed 時(shí),此時(shí) computed 重新計(jì)算

3computed 計(jì)算完成之后,會(huì)設(shè)置 watcher.dirty = false,以便于其他地方再次讀取時(shí),使用緩存,免于計(jì)算

watch原理

根據(jù) watch 的 api,我們需要了解三個(gè)地方:

1、監(jiān)聽的數(shù)據(jù)改變的時(shí),watch 如何工作

watch 在一開始初始化的時(shí)候,會(huì) 讀取 一遍 監(jiān)聽的數(shù)據(jù)的值,于是,此時(shí) 那個(gè)數(shù)據(jù)就收集到 watch 的 watcher 了

然后 你給 watch 設(shè)置的 handler ,watch 會(huì)放入 watcher 的更新函數(shù)中

當(dāng) 數(shù)據(jù)改變時(shí),通知 watch 的 watcher 進(jìn)行更新,于是 你設(shè)置的 handler 就被調(diào)用了

2、設(shè)置 immediate 時(shí),watch 如何工作

當(dāng)你設(shè)置了 immediate 時(shí),就不需要在 數(shù)據(jù)改變的時(shí)候 才會(huì)觸發(fā)。

而是在 初始化 watch 時(shí),在讀取了 監(jiān)聽的數(shù)據(jù)的值 之后,便立即調(diào)用一遍你設(shè)置的監(jiān)聽回調(diào),然后傳入剛讀取的值

3、設(shè)置了 deep 時(shí),watch 如何工作

  • 沒(méi)有設(shè)置 deep

因?yàn)樽x取了監(jiān)聽的 data 的屬性,watch 的 watcher 被收集在 這個(gè)屬性的 收集器中

  • 設(shè)置了 deep

因?yàn)樽x取了監(jiān)聽的data 的屬性,watch 的 watcher 被收集在 這個(gè)屬性的 收集器中

在讀取 data 屬性的時(shí)候,發(fā)現(xiàn)設(shè)置了 deep 而且值是一個(gè)對(duì)象,會(huì)遞歸遍歷這個(gè)值,把內(nèi)部所有屬性逐個(gè)讀取一遍,于是 屬性和 它的對(duì)象值內(nèi)每一個(gè)屬性 都會(huì)收集到 watch 的 watcher

于是,無(wú)論對(duì)象嵌套多深的屬性,只要改變了,會(huì)通知 相應(yīng)的 watch 的 watcher 去更新,于是 你設(shè)置的 watch 回調(diào)就被觸發(fā)了

computed和methods、watch的區(qū)別

  • computed是計(jì)算屬性,methods是方法,都可以實(shí)現(xiàn)對(duì) data 中的數(shù)據(jù)加工后再輸出。數(shù)據(jù)量大,需要緩存的時(shí)候用 computed ;每次確實(shí)需要重新加載,不需要緩存時(shí)用 methods 。

  • Watch是一個(gè)偵聽的動(dòng)作,用來(lái)觀察和響應(yīng)Vue實(shí)例上的數(shù)據(jù)變動(dòng)。它們都是vue對(duì)監(jiān)聽器的實(shí)現(xiàn),只不過(guò)computed主要用于對(duì)同步數(shù)據(jù)的處理,watch則主要用于觀測(cè)某個(gè)值的變化去完成一段開銷較大的復(fù)雜業(yè)務(wù)邏輯。

vue-router原理

VueRouter核心是,通過(guò)Vue.use注冊(cè)插件,在插件的install方法中獲取用戶配置的router對(duì)象。當(dāng)瀏覽器地址發(fā)生變化的時(shí)候,根據(jù)router對(duì)象匹配相應(yīng)路由,獲取組件,并將組件渲染到視圖上。

主要有三個(gè)重要點(diǎn):

  • 如何在install方法中獲取vue實(shí)例上的router屬性。

可以利用Vue.mixin混入聲明周期函數(shù)beforeCreate,在beforeCreate函數(shù)中可以獲取到Vue實(shí)例上的屬性并賦值到Vue原型鏈上。

_Vue.mixin({
 ? beforeCreate () {
 ? ?  if (this.$options.router) {
 ? ? ?  _Vue.prototype.$router = this.$options.router
 ? ?  }
 ? }
})
  • 如何觸發(fā)更新

hash模式下:

  1. 通過(guò)location.hash修改hash值,觸發(fā)更新。

  2. 通過(guò)監(jiān)聽hashchange事件監(jiān)聽瀏覽器前進(jìn)或者后退,觸發(fā)更新。

history模式下:

  1. 通過(guò)history對(duì)象方法修改瀏覽器地址,觸發(fā)更新。

  2. 通過(guò)監(jiān)聽popstate事件監(jiān)聽瀏覽器前進(jìn)或者后退,觸發(fā)更新。

  • 如何渲染router-view組件

  1. 通過(guò)Vue.observable在router實(shí)例上創(chuàng)建一個(gè)保存當(dāng)前路由的監(jiān)控對(duì)象current。

  2. 當(dāng)瀏覽器地址變化的時(shí)候,修改監(jiān)控對(duì)象current。

  3. 在router-view組件中監(jiān)聽監(jiān)控對(duì)象current的變化,當(dāng)current變化后,獲取用戶注冊(cè)的相應(yīng)component,并利用h函數(shù)將component渲染成vnodes,進(jìn)而更新頁(yè)面視圖。

Vue3

Vue2和Vue3響應(yīng)式原理的區(qū)別

主要就是Object.defineProperty和Proxy的區(qū)別

Vue3生命周期

選項(xiàng)式API和組合式API

  1. 組合式 API 的目的是增強(qiáng),不是取代選項(xiàng)式 API , vue3 對(duì)兩種 API 都支持

  2. 簡(jiǎn)單的場(chǎng)景使用選項(xiàng)式 API 更加簡(jiǎn)單方便

  3. 需要強(qiáng)烈支持 TS 的項(xiàng)目首選組合式 API

  4. 需要大量邏輯復(fù)用的場(chǎng)景首選組合式 API

VueX和Pinia的區(qū)別、優(yōu)劣

Pinia的優(yōu)點(diǎn)

  • 完整的 TypeScript 支持:與在 Vuex 中添加 TypeScript 相比,添加 TypeScript 更容易

  • 極其輕巧(體積約 1KB)

  • store 的 action 被調(diào)度為常規(guī)的函數(shù)調(diào)用,而不是使用 dispatch 方法或 MapAction 輔助函數(shù),這在 Vuex 中很常見

  • 支持多個(gè)Store

  • 支持 Vue devtools、SSR 和 webpack 代碼拆分

Pinia的缺點(diǎn)

  • 不支持時(shí)間旅行和編輯等調(diào)試功能

Vuex的優(yōu)點(diǎn)

  • 支持調(diào)試功能,如時(shí)間旅行和編輯

  • 適用于大型、高復(fù)雜度的Vue.js項(xiàng)目

Vuex的缺點(diǎn)

  • 從 Vue 3 開始,getter 的結(jié)果不會(huì)像計(jì)算屬性那樣緩存

  • Vuex 4有一些與類型安全相關(guān)的問(wèn)題

Vite好在哪為什么

vite優(yōu)點(diǎn):

  • webpack服務(wù)器啟動(dòng)速度比vite慢

由于vite啟動(dòng)的時(shí)候不需要打包,也就無(wú)需分析模塊依賴、編譯,所以啟動(dòng)速度非常快。當(dāng)瀏覽器請(qǐng)求需要的模塊時(shí),再對(duì)模塊進(jìn)行編譯,這種按需動(dòng)態(tài)編譯的模式,極大縮短了編譯時(shí)間,當(dāng)項(xiàng)目越大,文件越多時(shí),vite的開發(fā)時(shí)優(yōu)勢(shì)越明顯

  • vite熱更新比webpack快

vite在HRM方面,當(dāng)某個(gè)模塊內(nèi)容改變時(shí),讓瀏覽器去重新請(qǐng)求該模塊即可,而不是像webpack重新將該模塊的所有依賴重新編譯;

  • vite使用esbuild(Go 編寫) 預(yù)構(gòu)建依賴,而webpack基于nodejs, 比node快 10-100 倍

vite缺點(diǎn):

  • 生態(tài)不及webpack,加載器、插件不夠豐富

  • 打包到生產(chǎn)環(huán)境時(shí),vite使用傳統(tǒng)的rollup進(jìn)行打包,生產(chǎn)環(huán)境esbuild構(gòu)建對(duì)于css和代碼分割不夠友好。所以,vite的優(yōu)勢(shì)是體現(xiàn)在開發(fā)階段

  • 沒(méi)被大規(guī)模重度使用,會(huì)隱藏一些問(wèn)題

  • 項(xiàng)目的開發(fā)瀏覽器要支持esmodule

TS

對(duì)ts的理解

  • 定義:

添加了類型系統(tǒng)的 JavaScript,適用于任何規(guī)模的項(xiàng)目。類型系統(tǒng)按照「類型檢查的時(shí)機(jī)」來(lái)分類,可以分為動(dòng)態(tài)類型和靜態(tài)類型。

動(dòng)態(tài)類型是指在運(yùn)行時(shí)才會(huì)進(jìn)行類型檢查,這種語(yǔ)言的類型錯(cuò)誤往往會(huì)導(dǎo)致運(yùn)行時(shí)錯(cuò)誤。JavaScript 是一門解釋型語(yǔ)言,沒(méi)有編譯階段,所以它是動(dòng)態(tài)類型。

靜態(tài)類型是指編譯階段就能確定每個(gè)變量的類型,這種語(yǔ)言的類型錯(cuò)誤往往會(huì)導(dǎo)致語(yǔ)法錯(cuò)誤。TypeScript 在運(yùn)行前需要先編譯為 JavaScript,而在編譯階段就會(huì)進(jìn)行類型檢查,所以 TypeScript 是靜態(tài)類型

  • 好處:

項(xiàng)目帶來(lái)更高的可維護(hù)性,以及更少的 bug。

ts的數(shù)據(jù)類型

基礎(chǔ):

布爾值、數(shù)值、字符串、null、undefined 以及 ES6 中的新類型 Symbol 和 ES10 中的新類型 BigInt。

任意類型:

any、unknown

其他:

元祖、枚舉、void、聯(lián)合類型、類

never和void的區(qū)別

void表示沒(méi)有任何類型,該類型用作函數(shù)的返回值類型。若一個(gè)函數(shù)沒(méi)有返回值,那么該函數(shù)的返回值類型為void類型。

never表示不包含任何值,用永遠(yuǎn)沒(méi)有值

擁有void返回值類型的函數(shù)可以正常運(yùn)行,而never的則無(wú)法執(zhí)行,也無(wú)法終止,會(huì)拋出異常。

枚舉的理解

枚舉是一種數(shù)據(jù)類型,允許我們定義一組命名常量。這樣可以提高代碼的可讀性,便于后續(xù)的維護(hù)。枚舉的使用是通過(guò)enum關(guān)鍵字進(jìn)行定義。

類型可以分成:

  • 數(shù)字枚舉

當(dāng)我們聲明一個(gè)枚舉類型是,雖然沒(méi)有給它們賦值,但是它們的值其實(shí)是默認(rèn)的數(shù)字類型,而且默認(rèn)從0開始依次累加

如果我們將第一個(gè)值進(jìn)行賦值后,后面的值也會(huì)根據(jù)前一個(gè)值進(jìn)行累加1

  • 字符串枚舉

  • 異構(gòu)枚舉

數(shù)字枚舉和字符串枚舉結(jié)合起來(lái)混合起來(lái)使用

案例:后端的code、0-6對(duì)應(yīng)的日期

泛型

泛型程序設(shè)計(jì)(generic programming)是程序設(shè)計(jì)語(yǔ)言的一種風(fēng)格或范式。

泛型允許我們?cè)趶?qiáng)類型程序設(shè)計(jì)語(yǔ)言中編寫代碼時(shí)使用一些以后才指定的類型,在實(shí)例化時(shí)作為參數(shù)指明這些類型 在typescript中,定義函數(shù),接口或者類的時(shí)候,不預(yù)先定義好具體的類型,而在使用的時(shí)候在指定類型的一種特性。

泛型通過(guò)<>的形式進(jìn)行表述,可以聲明:

  • 函數(shù)

  • 接口

正確使用泛型可以達(dá)到多類型約束的目的。

項(xiàng)目

token超時(shí)處理

一般有三種處理方式: 前端處理 后端處理 雙token

  • 前端處理

    • 前端自己設(shè)置一個(gè)token有效期

    • 在獲得token的時(shí)候利用cookie-js自帶的方法存入一個(gè)時(shí)間戳

    • 在請(qǐng)求攔截器里面做判斷現(xiàn)在的時(shí)間減去存入token的時(shí)間是否超時(shí)了

    • 超時(shí)我的處理的是重新登錄(返回登陸頁(yè)面)

  • 后端處理

    • 如果token超時(shí),后端會(huì)返回一個(gè)狀態(tài)碼

    • 在響應(yīng)攔截器error中做判斷,看看返回的狀態(tài)碼是否登錄后端返回的這個(gè)token超時(shí)狀態(tài)碼,等于的話就做處理(返回登錄頁(yè)面)

  • 雙token處理

    • 有的時(shí)候登陸成功時(shí)后端會(huì)返回2個(gè)token給我們,一個(gè)是現(xiàn)在用的,一個(gè)是超時(shí)過(guò)后用的

    • 如果開始用的token超時(shí)了,那么做處理,調(diào)用第二個(gè)token設(shè)置到請(qǐng)求頭里面

    • 如果第二個(gè)也超時(shí)了,做處理(返回登錄頁(yè)面)

登錄頁(yè)面安全問(wèn)題

使用md5插件對(duì)密碼加密

發(fā)布通知功能怎么實(shí)現(xiàn)

websoket

項(xiàng)目剛上線出現(xiàn)bug

版本回退+拉分支出來(lái)修改bug

用什么進(jìn)行版本管理

git

Echarts在Vue里怎么使用

插件v-echarts,注冊(cè)組件使用

Echarts里的配置項(xiàng)不夠用怎么辦

換個(gè)插件,比如螞蟻的AntV

團(tuán)隊(duì)中有的人用vue2有的人用vue3怎么辦

技術(shù)棧選型就確認(rèn)了。下載vue3的版本,在 vue3 中也可以支持 vue2 選項(xiàng)API 寫法。然后在不同的單頁(yè)面里使用不同的語(yǔ)法。

項(xiàng)目?jī)?yōu)化

  • vue優(yōu)化:

  1. Vue-Router路由懶加載:Vue異步組件、Webpack的require.ensure()、ES6的import、

  2. 按需加載UI庫(kù)

  3. 如果首屏為登錄頁(yè),可以做成多入口

  4. 頁(yè)面使用骨架屏Skeleton Screen

  5. 服務(wù)端渲染SSR(將組件或頁(yè)面通過(guò)服務(wù)器生成html字符串,再發(fā)送到瀏覽器,最后將靜態(tài)標(biāo)記"混合"為客戶端上完全交互的應(yīng)用程序)

  • 網(wǎng)絡(luò)優(yōu)化:

  1. 減少 HTTP 請(qǐng)求數(shù)量

  2. 利用瀏覽器緩存,減小cookie大小,盡量用localStorage代替

  3. CDN加速,托管靜態(tài)文件

  4. 開啟 Gzip 壓縮:Nginx的gzip緩存壓縮、Webpack開啟gzip壓縮

  • js優(yōu)化:

  1. 節(jié)流、防抖

  2. 動(dòng)態(tài)加載、分頁(yè)加載(大數(shù)據(jù)渲染)

  3. 圖片懶加載(data-src)減少占用網(wǎng)絡(luò)帶寬

  4. 使用閉包時(shí),在函數(shù)結(jié)尾手動(dòng)刪除不需要的局部變量,尤其在緩存dom節(jié)點(diǎn)的情況下

  5. 異步加載js,async解析dom樹同時(shí)加載js,加載完暫停解析執(zhí)行js、defer解析dom樹同時(shí)加載js,解析完執(zhí)行js

  • css優(yōu)化:

  1. 不使用css表達(dá)式

  2. 減少回流(重排)

  3. 避免使用css文件嵌套過(guò)深

  • SEO優(yōu)化

PC端兼容問(wèn)題

img下的留白

解決方案:給img設(shè)定display:block。

如果圖片加a標(biāo)簽在IE9-中會(huì)有邊框

解決方案:給img設(shè)定border:none。

移動(dòng)端問(wèn)題

移動(dòng)端頁(yè)面滾動(dòng)滯澀感

css在body元素上添加-webkit-overflow-scrolling: touch;

修改移動(dòng)端的點(diǎn)擊高亮效果

* {-webkit-tap-highlight-color:rgba(0,0,0,0);}

滾動(dòng)穿透問(wèn)題

方案一:在html和body上設(shè)置overflow:hidden禁止?jié)L動(dòng)

方案二:阻止touchmove默認(rèn)事件

 ? ?var modal = document.getElementById('modal'); // 彈窗dom對(duì)象
 ? ?modal.addEventListener('touchmove', function(e) {
 ? ? ?e.preventDefault();
 ?  }, false);

方案三:position: fixed

方案一和三,如果需要保持滾動(dòng)條的位置需要用 js 保存滾動(dòng)條位置關(guān)閉的時(shí)候還原滾動(dòng)位置

在ios和andriod中,audio元素和video元素在無(wú)法自動(dòng)播放

應(yīng)對(duì)方案:觸屏即播

 ? ?$('html').one('touchstart',function(){
 ? ? ? ?audio.play()
 ?  })

iOS 系統(tǒng)中文輸入法輸入英文時(shí),字母之間可能會(huì)出現(xiàn)一個(gè)六分之一空格

可以通過(guò)正則去掉: this.value = this.value.replace(/\u2006/g, '')

IOS移動(dòng)端click事件300ms的延遲響應(yīng)

引入第三方插件fastclick可以解決在手機(jī)上點(diǎn)擊事件的300ms延遲

阻止旋轉(zhuǎn)屏幕時(shí)自動(dòng)調(diào)整字體大小

html, body, form, fieldset, p, div, h1, h2, h3, h4, h5, h6 {-webkit-text-size-adjust:none;}

圖片模糊問(wèn)題

根據(jù)不一樣的像素比,準(zhǔn)備不一樣的圖片,正常來(lái)說(shuō)是1px圖片像素 對(duì)應(yīng)1px物理像素,圖片的顯示就不會(huì)模糊啦,但是這樣的情況不多,不是非常重要,特殊需求的圖,我們不這么做。

.avatar{
 ? ?background-image: url(conardLi_1x.png);
}
@media only screen and (-webkit-min-device-pixel-ratio:2){
 ? ?.avatar{
 ? ? ? ?background-image: url(conardLi_2x.png);
 ?  }
}
@media only screen and (-webkit-min-device-pixel-ratio:3){
 ? ?.avatar{
 ? ? ? ?background-image: url(conardLi_3x.png);
 ?  }
}

移動(dòng)端某些情況下input的placeholder會(huì)出現(xiàn)文本位置偏上的現(xiàn)象

PC端設(shè)置line-height等于height能夠?qū)R,而移動(dòng)端仍然是偏上,解決是設(shè)置line-height:normal

h5底部輸入框被鍵盤遮擋問(wèn)題

可以通過(guò)監(jiān)聽移動(dòng)端軟鍵盤彈起,Element.scrollIntoView() 方法讓當(dāng)前的元素滾動(dòng)到瀏覽器窗口的可視區(qū)域內(nèi)。

window.addEventListener('resize', function() { ?
 ? ?if (document.activeElement.tagName === 'INPUT' || document.activeElement.tagName === 'TEXTAREA') { ? ?
 ? ? ? ?setTimeout(function() { ? ? ?
 ? ? ? ? ? ?if ('scrollIntoView' in document.activeElement) { ? ? ? ?
 ? ? ? ? ? ? ? ?document.activeElement.scrollIntoView(false) ? ? ?
 ? ? ? ? ?  } else { ? ? ? ?
 ? ? ? ? ? ? ? ?document.activeElement.scrollIntoViewIfNeeded(false) ? ? ?
 ? ? ? ? ?  } ? ?
 ? ? ?  }, 0) ?
 ?  }
})

移動(dòng)端如何做真機(jī)測(cè)試

方式1、公司有測(cè)試服務(wù)器,代碼放到測(cè)試服務(wù)器上,進(jìn)行手機(jī)訪問(wèn)測(cè)試

方式2、自己電腦上搭服務(wù)器,保證自己手機(jī)和電腦處于同一個(gè)局域網(wǎng),然后用手機(jī)進(jìn)行訪問(wèn)測(cè)試

H5和app的區(qū)別

  1. H5是通過(guò)鏈接進(jìn)行訪問(wèn),而APP是通過(guò)應(yīng)用程序進(jìn)行訪問(wèn)

  2. H5在應(yīng)用商店里面沒(méi)有,而APP是有的

  3. H5不需要審核就可以上線,而APP是需要審核的

  4. H5的響應(yīng)速度沒(méi)有APP快

  5. H5的開發(fā)成本比APP低文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-481485.html

到了這里,關(guān)于2023前端超全面試題,全是金三銀四面試真題整理!附答案。的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來(lái)自互聯(lián)網(wǎng)用戶投稿,該文觀點(diǎn)僅代表作者本人,不代表本站立場(chǎng)。本站僅提供信息存儲(chǔ)空間服務(wù),不擁有所有權(quán),不承擔(dān)相關(guān)法律責(zé)任。如若轉(zhuǎn)載,請(qǐng)注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實(shí)不符,請(qǐng)點(diǎn)擊違法舉報(bào)進(jìn)行投訴反饋,一經(jīng)查實(shí),立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費(fèi)用

相關(guān)文章

  • 金三銀四沒(méi)把握住,涼了...

    金三銀四沒(méi)把握住,涼了...

    大家好,前兩天跟朋友感慨,今年的銅三鐵四、裁員、疫情導(dǎo)致好多人都沒(méi)拿到offer!現(xiàn)在互聯(lián)網(wǎng)大廠終于迎來(lái)了應(yīng)屆生集中求職季。 對(duì)于想跳槽的軟件測(cè)試人來(lái)說(shuō),絕對(duì)是個(gè)找工作的好時(shí)機(jī)。這時(shí)候,很多高薪技術(shù)崗、管理崗的缺口和市場(chǎng)需求就出來(lái)了。 所以在這段時(shí)間想

    2023年04月15日
    瀏覽(36)
  • 金三銀四-JVM核心知識(shí)高頻面試題

    ? ? ? ? 又要快到一年一度的金三銀四,開始復(fù)習(xí)啦~! ? ? ? ? 每天一點(diǎn)點(diǎn)。。 目錄 一、JVM中的垃圾收集器有哪些,它們的工作原理是什么? 二、JVM中的類加載器有哪些,它們各自的作用是什么? 三、JVM中垃圾回收的算法有哪些? 四、JVM如何判斷對(duì)象是否死亡? 五、

    2024年02月01日
    瀏覽(24)
  • 金三銀四最近一次面試,被阿里P8測(cè)開虐慘了.....

    金三銀四最近一次面試,被阿里P8測(cè)開虐慘了.....

    都說(shuō)金三銀四漲薪季,我是著急忙慌的準(zhǔn)備簡(jiǎn)歷—— 5年軟件測(cè)試經(jīng)驗(yàn),可獨(dú)立測(cè)試大型產(chǎn)品項(xiàng)目,熟悉項(xiàng)目測(cè)試流程... 薪資要求? 5年測(cè)試經(jīng)驗(yàn)起碼能要個(gè)20K吧 我加班肝了一頁(yè)半簡(jiǎn)歷,投出去一周,面試電話倒是不少,自信滿滿去面試,現(xiàn)場(chǎng)被問(wèn)了這么幾個(gè)問(wèn)題——— “會(huì)

    2023年04月18日
    瀏覽(22)
  • 【Redis】Redis面試題詳解與使用案例(金三銀四面試專欄啟動(dòng))

    【Redis】Redis面試題詳解與使用案例(金三銀四面試專欄啟動(dòng))

    ??作者簡(jiǎn)介: 小明java問(wèn)道之路, 2022博客之星全國(guó)TOP3 ,專注于后端、中間件、計(jì)算機(jī)底層、架構(gòu)設(shè)計(jì)演進(jìn)與穩(wěn)定性建工設(shè)優(yōu)化。 文章內(nèi)容兼具廣度深度、大廠技術(shù)方案,對(duì)待技術(shù)喜歡推理加驗(yàn)證 ,就職于知名金融公司后端高級(jí)工程師。 ???????? ?? 熱衷分享,喜歡原

    2024年02月20日
    瀏覽(22)
  • 金三銀四-解鎖Java并發(fā)編程的藝術(shù):掌握多線程、同步和并發(fā)控制的精髓

    ? ? ? ? 又要快到一年一度的金三銀四,開始復(fù)習(xí)啦~! ? ? ? ? 每天一點(diǎn)點(diǎn)。。 目錄 一、Java中的volatile有什么作用? 二、解釋Java中的synchronized及其工作原理。 三、Java中的CAS操作是什么?它如何實(shí)現(xiàn)無(wú)鎖編程? 四、講述Java中的Lock接口及其與synchronized的區(qū)別

    2024年01月17日
    瀏覽(33)
  • 金三銀四跳槽季,JAVA面試擼題就來(lái)【笑小楓】微信小程序吧~

    金三銀四跳槽季,JAVA面試擼題就來(lái)【笑小楓】微信小程序吧~

    疫情已過(guò),金三銀四即將到來(lái),小伙伴們是否有跳槽的打算呢?不管有沒(méi)有,技術(shù)不能丟,讓我們一起來(lái)擼題吧。 博主最近整理了一批面試題,包括JAVA基礎(chǔ)、多線程與鎖、Redis、Spring事務(wù) 、Mybatis與Hibernate 、數(shù)據(jù)庫(kù) 、Spring 、JVM 、SpringBoot 、SpringCloud 、集合 、計(jì)算機(jī)網(wǎng)絡(luò)與

    2024年02月10日
    瀏覽(39)
  • Python 能寫游戲嗎?有沒(méi)有什么開源項(xiàng)目?,字節(jié)跳動(dòng)Python金三銀四解析

    Python 能寫游戲嗎?有沒(méi)有什么開源項(xiàng)目?,字節(jié)跳動(dòng)Python金三銀四解析

    代碼長(zhǎng)度:250 行哥評(píng)語(yǔ):最快教會(huì)女朋友的互動(dòng)游戲 4.連連看 使用模塊:pygame 代碼長(zhǎng)度:351 行哥評(píng)語(yǔ):網(wǎng)絡(luò)版的連連看可以用python腳本一秒完成 5.雷電 使用模塊:pygame 代碼長(zhǎng)度:490 行哥評(píng)語(yǔ):在物質(zhì)匱乏的年代,這個(gè)行哥真玩過(guò)通 6.俄羅斯方塊 使用模塊:pygame 代碼長(zhǎng)度

    2024年04月14日
    瀏覽(22)
  • 卷王都在偷偷準(zhǔn)備金三銀四了...

    卷王都在偷偷準(zhǔn)備金三銀四了...

    年終獎(jiǎng)沒(méi)發(fā); 簡(jiǎn)歷石沉大海; 發(fā)消息只讀不回 打開某招聘,看了看崗位,這個(gè)廠還不錯(cuò),可是要求好高,我啥都不會(huì)。 “哎,算了,我簡(jiǎn)歷還沒(méi)更新呢,我躺到6月份拿到年終獎(jiǎng)再跑路。” 這應(yīng)該是大多數(shù)軟件測(cè)試人狀態(tài)了吧, 我們習(xí)慣被一些悲觀的環(huán)境因素所影響,以至

    2023年04月08日
    瀏覽(31)
  • 金三銀四好像消失了,IT行業(yè)何時(shí)復(fù)蘇!

    疫情時(shí)候不敢離職,以為熬過(guò)來(lái)疫情了,行情會(huì)好一些,可是疫情結(jié)束了,反而行情更差了, 這是要哪樣 我心中不由一萬(wàn)個(gè) 草泥?? 路過(guò) 我心中不驚有了很多疑惑和感嘆 接著上一篇 一個(gè)28歲程序員入行自述和感受 自去年下半年以來(lái),互聯(lián)網(wǎng)行業(yè)一片寒冬傳言,眾多企業(yè)倒

    2024年02月03日
    瀏覽(27)
  • 前端2023最全面試題(javaScript、typeScript、vue2、vue3、html、css、uniapp、webpack、vite、react)

    答案:JavaScript中的閉包是一種函數(shù),它有權(quán)訪問(wèn)其詞法環(huán)境的變量和其它函數(shù)。這意味著,即使其包含它的函數(shù)已經(jīng)執(zhí)行完畢,其詞法環(huán)境仍然存在,因此可以訪問(wèn)其作用域內(nèi)的變量。 答案:回調(diào)函數(shù)是在某個(gè)特定事件之后執(zhí)行的函數(shù)。在JavaScript中,通常使用回調(diào)函數(shù)來(lái)處

    2024年02月06日
    瀏覽(35)

覺(jué)得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請(qǐng)作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包