2022秋招前端面試題(二)(附答案)

UDP協(xié)議為什么不可靠?

UDP在傳輸數(shù)據(jù)之前不需要先建立連接,遠(yuǎn)地主機(jī)的運(yùn)輸層在接收到UDP報(bào)文后,不需要確認(rèn),提供不可靠交付。總結(jié)就以下四點(diǎn):

  • 不保證消息交付:不確認(rèn),不重傳,無超時(shí)
  • 不保證交付順序:不設(shè)置包序號(hào),不重排,不會(huì)發(fā)生隊(duì)首阻塞
  • 不跟蹤連接狀態(tài):不必建立連接或重啟狀態(tài)機(jī)
  • 不進(jìn)行擁塞控制:不內(nèi)置客戶端或網(wǎng)絡(luò)反饋機(jī)制

瀏覽器是如何對(duì) HTML5 的離線儲(chǔ)存資源進(jìn)行管理和加載?

  • 在線的情況下,瀏覽器發(fā)現(xiàn) html 頭部有 manifest 屬性,它會(huì)請(qǐng)求 manifest 文件,如果是第一次訪問頁面 ,那么瀏覽器就會(huì)根據(jù) manifest 文件的內(nèi)容下載相應(yīng)的資源并且進(jìn)行離線存儲(chǔ)。如果已經(jīng)訪問過頁面并且資源已經(jīng)進(jìn)行離線存儲(chǔ)了,那么瀏覽器就會(huì)使用離線的資源加載頁面,然后瀏覽器會(huì)對(duì)比新的 manifest 文件與舊的 manifest 文件,如果文件沒有發(fā)生改變,就不做任何操作,如果文件改變了,就會(huì)重新下載文件中的資源并進(jìn)行離線存儲(chǔ)。
  • 離線的情況下,瀏覽器會(huì)直接使用離線存儲(chǔ)的資源。

說一下類組件和函數(shù)組件的區(qū)別?

1. 語法上的區(qū)別:

函數(shù)式組件是一個(gè)純函數(shù),它是需要接受props參數(shù)并且返回一個(gè)React元素就可以了。類組件是需要繼承React.Component的,而且class組件需要?jiǎng)?chuàng)建render并且返回React元素,語法上來講更復(fù)雜。

2. 調(diào)用方式

函數(shù)式組件可以直接調(diào)用,返回一個(gè)新的React元素;類組件在調(diào)用時(shí)是需要?jiǎng)?chuàng)建一個(gè)實(shí)例的,然后通過調(diào)用實(shí)例里的render方法來返回一個(gè)React元素。

3. 狀態(tài)管理

函數(shù)式組件沒有狀態(tài)管理,類組件有狀態(tài)管理。

4. 使用場(chǎng)景

類組件沒有具體的要求。函數(shù)式組件一般是用在大型項(xiàng)目中來分割大組件(函數(shù)式組件不用創(chuàng)建實(shí)例,所有更高效),一般情況下能用函數(shù)式組件就不用類組件,提升效率。
復(fù)制代碼

Set 和 Map有什么區(qū)別?

1、Map是鍵值對(duì),Set是值得集合,當(dāng)然鍵和值可以是任何得值
2、Map可以通過get方法獲取值,而set不能因?yàn)樗挥兄?3、都能通過迭代器進(jìn)行for...of 遍歷
4、Set的值是唯一的可以做數(shù)組去重,而Map由于沒有格式限制,可以做數(shù)據(jù)存儲(chǔ)
復(fù)制代碼

說一說js是什么語言

JavaScript是一種直譯式腳本語言,是一種動(dòng)態(tài)類型、弱類型、基于原型的語言,內(nèi)置支持類型。它的解釋器被稱為JavaScript引擎,為瀏覽器的一部分,廣泛用于客戶端的腳本語言,最早是在HTML(標(biāo)準(zhǔn)通用標(biāo)記語言下的一個(gè)應(yīng)用)網(wǎng)頁上使用,用來給HTML網(wǎng)頁增加動(dòng)態(tài)功能。

js語言是弱語言類型, 因此我們?cè)陧?xiàng)目開發(fā)中當(dāng)我們隨意更該某個(gè)變量的數(shù)據(jù)類型后
有可能會(huì)導(dǎo)致其他引用這個(gè)變量的方法中報(bào)錯(cuò)等等。
復(fù)制代碼

說說瀏覽器緩存

緩存可以減少網(wǎng)絡(luò) IO 消耗,提高訪問速度。瀏覽器緩存是一種操作簡(jiǎn)單、效果顯著的前端性能優(yōu)化手段
很多時(shí)候,大家傾向于將瀏覽器緩存簡(jiǎn)單地理解為“HTTP 緩存”。
但事實(shí)上,瀏覽器緩存機(jī)制有四個(gè)方面,它們按照獲取資源時(shí)請(qǐng)求的優(yōu)先級(jí)依次排列如下:

Memory Cache
Service Worker Cache
HTTP Cache
Push Cache

緩存它又分為強(qiáng)緩存和協(xié)商緩存。優(yōu)先級(jí)較高的是強(qiáng)緩存,在命中強(qiáng)緩存失敗的情況下,才會(huì)走協(xié)商緩存
    實(shí)現(xiàn)強(qiáng)緩存,過去我們一直用 expires。    當(dāng)服務(wù)器返回響應(yīng)時(shí),在 Response Headers 中將過期時(shí)間寫入 expires 字段,現(xiàn)在一般使用Cache-Control 兩者同時(shí)出現(xiàn)使用Cache-Control         協(xié)商緩存,Last-Modified 是一個(gè)時(shí)間戳,如果我們啟用了協(xié)商緩存,它會(huì)在首次請(qǐng)求時(shí)隨著 Response Headers 返回:每次請(qǐng)求去判斷這個(gè)時(shí)間戳是否發(fā)生變化。    從而去決定你是304讀取緩存還是給你返回最新的數(shù)據(jù)
復(fù)制代碼

原型

構(gòu)造函數(shù)是一種特殊的方法,主要用來在創(chuàng)建對(duì)象時(shí)初始化對(duì)象。每個(gè)構(gòu)造函數(shù)都有prototype(原型)(箭頭函數(shù)以及Function.prototype.bind()沒有)屬性,
這個(gè)prototype(原型)屬性是一個(gè)指針,指向一個(gè)對(duì)象,這個(gè)對(duì)象的用途是包含特定類型的所有實(shí)例共享的
屬性和方法,即這個(gè)原型對(duì)象是用來給實(shí)例對(duì)象共享屬性和方法的。每個(gè)實(shí)例對(duì)象的__proto__都指向這個(gè)
構(gòu)造函數(shù)/類的prototype屬性。

面向?qū)ο蟮娜筇匦裕豪^承/多態(tài)/封裝

關(guān)于new操作符:

1. new執(zhí)行的函數(shù), 函數(shù)內(nèi)部默認(rèn)生成了一個(gè)對(duì)象

2. 函數(shù)內(nèi)部的this默認(rèn)指向了這個(gè)new生成的對(duì)象

3. new執(zhí)行函數(shù)生成的這個(gè)對(duì)象, 是函數(shù)的默認(rèn)返回值

ES5例子:
function Person(obj) {
    this.name = obj.name
    this.age= obj.age
}
// 原型方法
Person.prototype.say = function() {
  console.log('你好,', this.name )
}
// p為實(shí)例化對(duì)象,new Person()這個(gè)操作稱為構(gòu)造函數(shù)的實(shí)例化
let p = new Person({name: '番茄', age: '27'})
console.log(p.name, p.age)
p.say()

ES6例子:
class Person{
    constructor(obj) {
      this.name = obj.name
        this.age= obj.age
  }
  say() {
      console.log(this.name)
  }
}

let p = new Person({name: 'ES6-番茄', age: '27'})
console.log(p.name, p.age)
p.say()
復(fù)制代碼

webpack配置入口出口

module.exports={
    //入口文件的配置項(xiàng)
    entry:{},
    //出口文件的配置項(xiàng)
    output:{},
    //模塊:例如解讀CSS,圖片如何轉(zhuǎn)換,壓縮
    module:{},
    //插件,用于生產(chǎn)模版和各項(xiàng)功能
    plugins:[],
    //配置webpack開發(fā)服務(wù)功能
    devServer:{}
}
簡(jiǎn)單描述了一下這幾個(gè)屬性是干什么的。
描述一下npm run dev / npm run build執(zhí)行的是哪些文件
通過配置proxyTable來達(dá)到開發(fā)環(huán)境跨域的問題,然后又可以擴(kuò)展和他聊聊跨域的產(chǎn)生,如何跨域
最后可以在聊聊webpack的優(yōu)化,例如babel-loader的優(yōu)化,gzip壓縮等等
復(fù)制代碼

說一下vue3.0你了解多少?

 <!-- 響應(yīng)式原理的改變 Vue3.x 使用Proxy取代 Vue2.x 版本的Object.defineProperty -->
 <!-- 組件選項(xiàng)聲明方式Vue3.x 使用Composition API setup 是Vue3.x新增的一個(gè)選項(xiàng),他
    是組件內(nèi)使用Composition API 的入口 -->
 <!-- 模板語法變化slot具名插槽語法 自定義指令 v-model 升級(jí) -->
 <!-- 其它方面的更改Suspense支持Fragment(多個(gè)根節(jié)點(diǎn)) 和Protal (在dom其他部分渲染組建內(nèi)容)組件
     針對(duì)一些特殊的場(chǎng)景做了處理。基于treeshaking優(yōu)化,提供了更多的內(nèi)置功能。 -->
復(fù)制代碼

你在工作終于到那些問題,解決方法是什么

經(jīng)常遇到的問題就是Cannot read property ‘prototype’ of undefined
解決辦法通過瀏覽器報(bào)錯(cuò)提示代碼定位問題,解決問題

Vue項(xiàng)目中遇到視圖不更新,方法不執(zhí)行,埋點(diǎn)不觸發(fā)等問題
一般解決方案查看瀏覽器報(bào)錯(cuò),查看代碼運(yùn)行到那個(gè)階段未之行結(jié)束,閱讀源碼以及相關(guān)文檔等
然后舉出來最近開發(fā)的項(xiàng)目中遇到的算是兩個(gè)比較大的問題。
復(fù)制代碼

說一下data為什么是一個(gè)函數(shù)而不是一個(gè)對(duì)象?

JavaScript中的對(duì)象是引用類型的數(shù)據(jù),當(dāng)多個(gè)實(shí)例引用同一個(gè)對(duì)象時(shí),只要一個(gè)實(shí)例對(duì)這個(gè)對(duì)象進(jìn)行操作,其他實(shí)例中的數(shù)據(jù)也會(huì)發(fā)生變化。而在Vue中,我們更多的是想要復(fù)用組件,那就需要每個(gè)組件都有自己的數(shù)據(jù),這樣組件之間才不會(huì)相互干擾。所以組件的數(shù)據(jù)不能寫成對(duì)象的形式,而是要寫成函數(shù)的形式。數(shù)據(jù)以函數(shù)返回值的形式定義,這樣當(dāng)我們每次復(fù)用組件的時(shí)候,就會(huì)返回一個(gè)新的data,也就是說每個(gè)組件都有自己的私有數(shù)據(jù)空間,它們各自維護(hù)自己的數(shù)據(jù),不會(huì)干擾其他組件的正常運(yùn)行。

說一下常見的git操作

git branch 查看本地所有分支
git status 查看當(dāng)前狀態(tài) 
git commit 提交 
git branch -a 查看所有的分支
git branch -r 查看遠(yuǎn)程所有分支
git commit -am "nit" 提交并且加注釋 
git remote add origin git@192.168.1.119:ndshow
git push origin master 將文件給推到服務(wù)器上 
git remote show origin 顯示遠(yuǎn)程庫origin里的資源 
git push origin master:develop
git push origin master:hb-dev 將本地庫與服務(wù)器上的庫進(jìn)行關(guān)聯(lián) 
git checkout --track origin/dev 切換到遠(yuǎn)程dev分支
git branch -D master develop 刪除本地庫develop
git checkout -b dev 建立一個(gè)新的本地分支dev
git merge origin/dev 將分支dev與當(dāng)前分支進(jìn)行合并
git checkout dev 切換到本地dev分支
git remote show 查看遠(yuǎn)程庫
git add .
git rm 文件名(包括路徑) 從git中刪除指定文件
git clone git://github.com/schacon/grit.git 從服務(wù)器上將代碼給拉下來
git config --list 看所有用戶
git ls-files 看已經(jīng)被提交的
git rm [file name] 刪除一個(gè)文件
git commit -a 提交當(dāng)前repos的所有的改變
git add [file name] 添加一個(gè)文件到git index
git commit -v 當(dāng)你用-v參數(shù)的時(shí)候可以看commit的差異
git commit -m "This is the message describing the commit" 添加commit信息
git commit -a -a是代表add,把所有的change加到git index里然后再commit
git commit -a -v 一般提交命令
git log 看你commit的日志
git diff 查看尚未暫存的更新
git rm a.a 移除文件(從暫存區(qū)和工作區(qū)中刪除)
git rm --cached a.a 移除文件(只從暫存區(qū)中刪除)
git commit -m "remove" 移除文件(從Git中刪除)
git rm -f a.a 強(qiáng)行移除修改后文件(從暫存區(qū)和工作區(qū)中刪除)
git diff --cached 或 $ git diff --staged 查看尚未提交的更新
git stash push 將文件給push到一個(gè)臨時(shí)空間中
git stash pop 將文件從臨時(shí)空間pop下來


webpack3和webpack4區(qū)別

1.mode

webpack增加了一個(gè)mode配置,只有兩種值development | production。對(duì)不同的環(huán)境他會(huì)啟用不同的配置。

2.CommonsChunkPlugin

CommonChunksPlugin已經(jīng)從webpack4中移除。
可使用optimization.splitChunks進(jìn)行模塊劃分(提取公用代碼)。
但是需要注意一個(gè)問題,默認(rèn)配置只會(huì)對(duì)異步請(qǐng)求的模塊進(jìn)行提取拆分,如果要對(duì)entry進(jìn)行拆分
需要設(shè)置optimization.splitChunks.chunks = 'all'。

3.webpack4使用MiniCssExtractPlugin取代ExtractTextWebpackPlugin。

4.代碼分割。

使用動(dòng)態(tài)import,而不是用system.import或者require.ensure

5.vue-loader。

使用vue-loader插件為.vue文件中的各部分使用相對(duì)應(yīng)的loader,比如css-loader等

6.UglifyJsPlugin

現(xiàn)在也不需要使用這個(gè)plugin了,只需要使用optimization.minimize為true就行,production mode下面自動(dòng)為true

optimization.minimizer可以配置你自己的壓縮程序
復(fù)制代碼

New操作符做了什么事情?

1、首先創(chuàng)建了一個(gè)新對(duì)象
2、設(shè)置原型,將對(duì)象的原型設(shè)置為函數(shù)的prototype對(duì)象
3、讓函數(shù)的this指向這個(gè)對(duì)象,執(zhí)行構(gòu)造函數(shù)的代碼(為這個(gè)新對(duì)象添加屬性)
4、判斷函數(shù)的返回值類型,如果是值類型,返回創(chuàng)建的對(duì)象。如果是引用類型,就返回這個(gè)引用類型的對(duì)象
復(fù)制代碼

JS閉包,你了解多少?

應(yīng)該有面試官問過你:

  1. 什么是閉包?
  2. 閉包有哪些實(shí)際運(yùn)用場(chǎng)景?
  3. 閉包是如何產(chǎn)生的?
  4. 閉包產(chǎn)生的變量如何被回收?

這些問題其實(shí)都可以被看作是同一個(gè)問題,那就是面試官在問你:你對(duì)JS閉包了解多少?

來總結(jié)一下我聽到過的答案,盡量完全復(fù)原候選人面試的時(shí)候說的原話。

答案1: 就是一個(gè)function里面return了一個(gè)子函數(shù),子函數(shù)訪問了外面那個(gè)函數(shù)的變量。

答案2: for循環(huán)里面可以用閉包來解決問題。

for(var i = 0; i < 10; i++){
    setTimeout(()=>console.log(i),0)
}
// 控制臺(tái)輸出10遍10.
for(var i = 0; i < 10; i++){
    (function(a){
    setTimeout(()=>console.log(a),0)
    })(i)
}
 // 控制臺(tái)輸出0-9
復(fù)制代碼

答案3: 當(dāng)前作用域產(chǎn)產(chǎn)生了對(duì)父作用域的引用。

答案4: 不知道。是跟瀏覽器的垃圾回收機(jī)制有關(guān)嗎?

開杠了。請(qǐng)問,小伙伴的答案和以上的內(nèi)容有多少相似程度?

其實(shí),拿著這些問題好好想想,你就會(huì)發(fā)現(xiàn)這些問題都只是為了最終那一個(gè)問題。

閉包的底層實(shí)現(xiàn)原理

1. JS執(zhí)行上下文

我們都知道,我們手寫的js代碼是要經(jīng)過瀏覽器V8進(jìn)行預(yù)編譯后才能真正的被執(zhí)行。例如變量提升、函數(shù)提升。舉個(gè)栗子。

// 栗子:
var d = 'abc';
function a(){
    console.log("函數(shù)a");
};
console.log(a);   // ? a(){ console.log("函數(shù)a"); }
a();              // '函數(shù)a'
var a = "變量a";  
console.log(a);   // '變量a'
a();              // a is not a function
var c = 123;

// 輸出結(jié)果及順序:
// ? a(){ console.log("函數(shù)a"); }
// '函數(shù)a'
// '變量a'
// a is not a function

// 栗子預(yù)編后相當(dāng)于:
function a(){
    console.log("函數(shù)a");
};
var d;
console.log(a);  // ? a(){ console.log("函數(shù)a"); }
a();              // '函數(shù)a'

a = "變量a";     // 此時(shí)變量a賦值,函數(shù)聲明被覆蓋

console.log(a); // "變量a"
a();         // a is not a function

復(fù)制代碼

那么問題來了。 請(qǐng)問是誰來執(zhí)行預(yù)編譯操作的?那這個(gè)誰又是在哪里進(jìn)行預(yù)編譯的?

是的,你的疑惑沒有錯(cuò)。js代碼運(yùn)行需要一個(gè)運(yùn)行環(huán)境,那這個(gè)環(huán)境就是執(zhí)行上下文。 是的,js運(yùn)行前的預(yù)編譯也是在這個(gè)環(huán)境中進(jìn)行。

js執(zhí)行上下文分三種:

  • 全局執(zhí)行上下文: 代碼開始執(zhí)行時(shí)首先進(jìn)入的環(huán)境。
  • 函數(shù)執(zhí)行上下文:函數(shù)調(diào)用時(shí),會(huì)開始執(zhí)行函數(shù)中的代碼。
  • eval執(zhí)行上下文:不建議使用,可忽略。

那么,執(zhí)行上下文的周期,分為兩個(gè)階段:

  • 創(chuàng)建階段
    • 創(chuàng)建詞法環(huán)境
    • 生成變量對(duì)象(VO),建立作用域鏈作用域鏈作用域鏈(重要的事說三遍)
    • 確認(rèn)this指向,并綁定this
  • 執(zhí)行階段。這個(gè)階段進(jìn)行變量賦值,函數(shù)引用及執(zhí)行代碼。

你現(xiàn)在猜猜看,預(yù)編譯是發(fā)生在什么時(shí)候?

噢,我忘記說了,其實(shí)與編譯還有另一個(gè)稱呼:執(zhí)行期上下文

預(yù)編譯發(fā)生在函數(shù)執(zhí)行之前。預(yù)編譯四部曲為:

  1. 創(chuàng)建AO對(duì)象
  2. 找形參和變量聲明,將變量和形參作為AO屬性名,值為undefined
  3. 將實(shí)參和形參相統(tǒng)一
  4. 在函數(shù)體里找到函數(shù)聲明,值賦予函數(shù)體。最后程序輸出變量值的時(shí)候,就是從AO對(duì)象中拿。

所以,預(yù)編譯真正的結(jié)果是:

var AO = {
    a = function a(){console.log("函數(shù)a");};
    d = 'abc'
}
復(fù)制代碼

我們重新來。

1. 什么叫變量對(duì)象?

變量對(duì)象是 js 代碼在進(jìn)入執(zhí)行上下文時(shí),js 引擎在內(nèi)存中建立的一個(gè)對(duì)象,用來存放當(dāng)前執(zhí)行環(huán)境中的變量。

2. 變量對(duì)象(VO)的創(chuàng)建過程

變量對(duì)象的創(chuàng)建,是在執(zhí)行上下文創(chuàng)建階段,依次經(jīng)過以下三個(gè)過程:

  • 創(chuàng)建 arguments 對(duì)象。

    對(duì)于函數(shù)執(zhí)行環(huán)境,首先查詢是否有傳入的實(shí)參,如果有,則會(huì)將參數(shù)名是實(shí)參值組成的鍵值對(duì)放入arguments 對(duì)象中。否則,將參數(shù)名和 undefined組成的鍵值對(duì)放入 arguments 對(duì)象中。

//舉個(gè)栗子 
function bar(a, b, c) {
    console.log(arguments);  // [1, 2]
    console.log(arguments[2]); // undefined
}
bar(1,2)
復(fù)制代碼
  • 當(dāng)遇到同名的函數(shù)時(shí),后面的會(huì)覆蓋前面的。
console.log(a); // function a() {console.log('Is a ?') }
function a() {
    console.log('Is a');
}
function a() {
  console.log('Is a ?')
}

/**ps: 在執(zhí)行第一行代碼之前,函數(shù)聲明已經(jīng)創(chuàng)建完成.后面的對(duì)之前的聲明進(jìn)行了覆蓋。**/
復(fù)制代碼
  • 檢查當(dāng)前環(huán)境中的變量聲明并賦值為undefined。當(dāng)遇到同名的函數(shù)聲明,為了避免函數(shù)被賦值為 undefined ,會(huì)忽略此聲明
console.log(a); // function a() {console.log('Is a ?') }
console.log(b); // undefined
function a() {
  console.log('Is a ');
}
function a() {
console.log('Is a ?');
}
var b = 'Is b';
var a = 10086;

/**這段代碼執(zhí)行一下,你會(huì)發(fā)現(xiàn) a 打印結(jié)果仍舊是一個(gè)函數(shù),而 b 則是 undefined。**/
復(fù)制代碼

根據(jù)以上三個(gè)步驟,對(duì)于變量提升也就知道是怎么回事了。

3. 變量對(duì)象變?yōu)榛顒?dòng)對(duì)象

執(zhí)行上下文的第二個(gè)階段,稱為執(zhí)行階段,在此時(shí),會(huì)進(jìn)行變量賦值,函數(shù)引用并執(zhí)行其他代碼,此時(shí),變量對(duì)象變?yōu)榛顒?dòng)對(duì)象。

我們還是舉上面的例子:

console.log(a); // function a() {console.log('fjdsfs') }
console.log(b); // undefined
function a() {
   console.log('Is a');
}
function a() {
 console.log('Is a?');
}
var b = 'Is b';
console.log(b); // 'Is b'
var a = 10086; 
console.log(a);  // 10086
var b = 'Is b?';
console.log(b); // 'Is b?'
復(fù)制代碼

在上面的代碼中,代碼真正開始執(zhí)行是從第一行 console.log() 開始的,自這之前,執(zhí)行上下文是這樣的:

// 創(chuàng)建過程
EC= {
  VO: {}; // 創(chuàng)建變量對(duì)象
  scopeChain: {}; // 作用域鏈
}
VO = {
  argument: {...}; // 當(dāng)前為全局上下文,所以這個(gè)屬性值是空的
  a: <a reference> // 函數(shù) a  的引用地址  b: undefiend  // 見上文創(chuàng)建變量對(duì)象的第三步}

復(fù)制代碼
詞法作用域(Lexical scope

這里想說明,我們?cè)诤瘮?shù)執(zhí)行上下文中有變量,在全局執(zhí)行上下文中有變量。JavaScript的一個(gè)復(fù)雜之處在于它如何查找變量,如果在函數(shù)執(zhí)行上下文中找不到變量,它將在調(diào)用上下文中尋找它,如果在它的調(diào)用上下文中沒有找到,就一直往上一級(jí),直到它在全局執(zhí)行上下文中查找為止。(如果最后找不到,它就是 undefined)。

再來舉個(gè)栗子:

 1: let top = 0; // 
 2: function createWarp() {
 3:   function add(a, b) {
 4:     let ret = a + b
 5:     return ret
 6:   }
 7:   return add
 8: }
 9: let sum = createWarp()
10: let result = sum(top, 8)
11: console.log('result:',result)


復(fù)制代碼

分析過程如下:

  • 在全局上下文中聲明變量top 并賦值為0.
  • 2 - 8行。在全局執(zhí)行上下文中聲明了一個(gè)名為 createWarp 的變量,并為其分配了一個(gè)函數(shù)定義。其中第3-7行描述了其函數(shù)定義,并將函數(shù)定義存儲(chǔ)到那個(gè)變量(createWarp)中。
  • 第9行。我們?cè)谌謭?zhí)行上下文中聲明了一個(gè)名為 sum 的新變量,暫時(shí),值為 undefined
  • 第9行。遇到(),表明需要執(zhí)行或調(diào)用一個(gè)函數(shù)。那么查找全局執(zhí)行上下文的內(nèi)存并查找名為 createWarp 的變量。 明顯,已經(jīng)在步驟2中創(chuàng)建完畢。接著,調(diào)用它。
  • 調(diào)用函數(shù)時(shí),回到第2行。創(chuàng)建一個(gè)新的createWarp執(zhí)行上下文。我們可以在 createWarp 的執(zhí)行上下文中創(chuàng)建自有變量。js 引擎createWarp 的上下文添加到調(diào)用堆棧(call stack)。因?yàn)檫@個(gè)函數(shù)沒有參數(shù),直接跳到它的主體部分.
  • 3 - 6 行。我們有一個(gè)新的函數(shù)聲明,createWarp執(zhí)行上下文中創(chuàng)建一個(gè)變量 addadd 只存在于 createWarp 執(zhí)行上下文中, 其函數(shù)定義存儲(chǔ)在名為 add 的自有變量中。
  • 第7行,我們返回變量 add 的內(nèi)容。js引擎查找一個(gè)名為 add 的變量并找到它. 第4行和第5行括號(hào)之間的內(nèi)容構(gòu)成該函數(shù)定義。
  • createWarp 調(diào)用完畢,createWarp 執(zhí)行上下文將被銷毀。add 變量也跟著被銷毀。add 函數(shù)定義仍然存在,因?yàn)樗祷夭①x值給了 sum 變量。 (ps: 這才是閉包產(chǎn)生的變量存于內(nèi)存當(dāng)中的真相
  • 接下來就是簡(jiǎn)單的執(zhí)行過程,不再贅述。。
  • ……
  • 代碼執(zhí)行完畢,全局執(zhí)行上下文被銷毀。sum 和 result 也跟著被銷毀。

小結(jié)一下

現(xiàn)在,如果再讓你回答什么是閉包,你能答出多少?

其實(shí),大家說的都對(duì)。不管是函數(shù)返回一個(gè)函數(shù),還是產(chǎn)生了外部作用域的引用,都是有道理的。

所以,什么是閉包?

  • 解釋一下作用域鏈?zhǔn)侨绾萎a(chǎn)生的。
  • 解釋一下js執(zhí)行上下文的創(chuàng)建、執(zhí)行過程。
  • 解釋一下閉包所產(chǎn)生的變量放在哪了。
  • 最后請(qǐng)把以上3點(diǎn)結(jié)合起來說給面試官聽。

深拷貝淺拷貝

淺拷貝:淺拷貝通過ES6新特性O(shè)bject.assign()或者通過擴(kuò)展運(yùn)算法...來達(dá)到淺拷貝的目的,淺拷貝修改
副本,不會(huì)影響原數(shù)據(jù),但缺點(diǎn)是淺拷貝只能拷貝第一層的數(shù)據(jù),且都是值類型數(shù)據(jù),如果有引用型數(shù)據(jù),修改
副本會(huì)影響原數(shù)據(jù)。

深拷貝:通過利用JSON.parse(JSON.stringify())來實(shí)現(xiàn)深拷貝的目的,但利用JSON拷貝也是有缺點(diǎn)的,
當(dāng)要拷貝的數(shù)據(jù)中含有undefined/function/symbol類型是無法進(jìn)行拷貝的,當(dāng)然我們想項(xiàng)目開發(fā)中需要
深拷貝的數(shù)據(jù)一般不會(huì)含有以上三種類型,如有需要可以自己在封裝一個(gè)函數(shù)來實(shí)現(xiàn)。
復(fù)制代碼

說一下你對(duì)盒模型的理解?

CSS3中的盒模型有以下兩種:標(biāo)準(zhǔn)盒模型、IE盒模型
盒模型都是由四個(gè)部分組成的,分別是margin、border、padding和content
標(biāo)準(zhǔn)盒模型和IE盒模型的區(qū)別在于設(shè)置width和height時(shí), 所對(duì)應(yīng)的范圍不同
1、標(biāo)準(zhǔn)盒模型的width和height屬性的范圍只包含了content
2、IE盒模型的width和height屬性的范圍包含了border、padding和content
可以通過修改元素的box-sizing屬性來改變?cè)氐暮心P停?1、box-sizing:content-box表示標(biāo)準(zhǔn)盒模型(默認(rèn)值)
2、box-sizing:border-box表示IE盒模型(怪異盒模型)
復(fù)制代碼

CDN的作用

CDN一般會(huì)用來托管Web資源(包括文本、圖片和腳本等),可供下載的資源(媒體文件、軟件、文檔等),應(yīng)用程序(門戶網(wǎng)站等)。使用CDN來加速這些資源的訪問。

(1)在性能方面,引入CDN的作用在于:

  • 用戶收到的內(nèi)容來自最近的數(shù)據(jù)中心,延遲更低,內(nèi)容加載更快
  • 部分資源請(qǐng)求分配給了CDN,減少了服務(wù)器的負(fù)載

(2)在安全方面,CDN有助于防御DDoS、MITM等網(wǎng)絡(luò)攻擊:

  • 針對(duì)DDoS:通過監(jiān)控分析異常流量,限制其請(qǐng)求頻率
  • 針對(duì)MITM:從源服務(wù)器到 CDN 節(jié)點(diǎn)到 ISP(Internet Service Provider),全鏈路 HTTPS 通信

除此之外,CDN作為一種基礎(chǔ)的云服務(wù),同樣具有資源托管、按需擴(kuò)展(能夠應(yīng)對(duì)流量高峰)等方面的優(yōu)勢(shì)。

代碼輸出結(jié)果

Promise.resolve().then(() => {
  return new Error('error!!!')
}).then(res => {
  console.log("then: ", res)
}).catch(err => {
  console.log("catch: ", err)
})
復(fù)制代碼

輸出結(jié)果如下:

"then: " "Error: error!!!"
復(fù)制代碼

返回任意一個(gè)非 promise 的值都會(huì)被包裹成 promise 對(duì)象,因此這里的return new Error('error!!!')也被包裹成了return Promise.resolve(new Error('error!!!')),因此它會(huì)被then捕獲而不是catch。

Vuex有哪些基本屬性?為什么 Vuex 的 mutation 中不能做異步操作?

有五種,分別是 State、 Getter、Mutation 、Action、 Module
1、state => 基本數(shù)據(jù)(數(shù)據(jù)源存放地)
2、getters => 從基本數(shù)據(jù)派生出來的數(shù)據(jù)
3、mutations => 提交更改數(shù)據(jù)的方法,同步
4、actions => 像一個(gè)裝飾器,包裹mutations,使之可以異步。
5、modules => 模塊化Vuex

1、Vuex中所有的狀態(tài)更新的唯一途徑都是mutation,異步操作通過 Action 來提交 mutation實(shí)現(xiàn),這樣可以方便地跟蹤每一個(gè)狀態(tài)的變化,從而能夠?qū)崿F(xiàn)一些工具幫助更好地了解我們的應(yīng)用。
2、每個(gè)mutation執(zhí)行完成后都會(huì)對(duì)應(yīng)到一個(gè)新的狀態(tài)變更,這樣devtools就可以打個(gè)快照存下來,然后就可以實(shí)現(xiàn) time-travel 了。如果mutation支持異步操作,就沒有辦法知道狀態(tài)是何時(shí)更新的,無法很好的進(jìn)行狀態(tài)的追蹤,給調(diào)試帶來困難。
復(fù)制代碼
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 230,431評(píng)論 6 544
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 99,637評(píng)論 3 429
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 178,555評(píng)論 0 383
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)。 經(jīng)常有香客問我,道長(zhǎng),這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,900評(píng)論 1 318
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 72,629評(píng)論 6 412
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 55,976評(píng)論 1 328
  • 那天,我揣著相機(jī)與錄音,去河邊找鬼。 笑死,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,976評(píng)論 3 448
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 43,139評(píng)論 0 290
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 49,686評(píng)論 1 336
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 41,411評(píng)論 3 358
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 43,641評(píng)論 1 374
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 39,129評(píng)論 5 364
  • 正文 年R本政府宣布,位于F島的核電站,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 44,820評(píng)論 3 350
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 35,233評(píng)論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,567評(píng)論 1 295
  • 我被黑心中介騙來泰國(guó)打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 52,362評(píng)論 3 400
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 48,604評(píng)論 2 380

推薦閱讀更多精彩內(nèi)容