UDP協(xié)議為什么不可靠?
UDP在傳輸數(shù)據(jù)之前不需要先建立連接骑丸,遠地主機的運輸層在接收到UDP報文后,不需要確認妒貌,提供不可靠交付通危。總結(jié)就以下四點:
- 不保證消息交付:不確認灌曙,不重傳菊碟,無超時
- 不保證交付順序:不設(shè)置包序號,不重排在刺,不會發(fā)生隊首阻塞
- 不跟蹤連接狀態(tài):不必建立連接或重啟狀態(tài)機
- 不進行擁塞控制:不內(nèi)置客戶端或網(wǎng)絡(luò)反饋機制
瀏覽器是如何對 HTML5 的離線儲存資源進行管理和加載逆害?
- 在線的情況下,瀏覽器發(fā)現(xiàn) html 頭部有 manifest 屬性蚣驼,它會請求 manifest 文件魄幕,如果是第一次訪問頁面 ,那么瀏覽器就會根據(jù) manifest 文件的內(nèi)容下載相應(yīng)的資源并且進行離線存儲颖杏。如果已經(jīng)訪問過頁面并且資源已經(jīng)進行離線存儲了纯陨,那么瀏覽器就會使用離線的資源加載頁面,然后瀏覽器會對比新的 manifest 文件與舊的 manifest 文件留储,如果文件沒有發(fā)生改變翼抠,就不做任何操作,如果文件改變了获讳,就會重新下載文件中的資源并進行離線存儲阴颖。
- 離線的情況下,瀏覽器會直接使用離線存儲的資源丐膝。
說一下類組件和函數(shù)組件的區(qū)別?
1. 語法上的區(qū)別:
函數(shù)式組件是一個純函數(shù)量愧,它是需要接受props參數(shù)并且返回一個React元素就可以了钾菊。類組件是需要繼承React.Component的,而且class組件需要創(chuàng)建render并且返回React元素侠畔,語法上來講更復(fù)雜结缚。
2. 調(diào)用方式
函數(shù)式組件可以直接調(diào)用,返回一個新的React元素软棺;類組件在調(diào)用時是需要創(chuàng)建一個實例的红竭,然后通過調(diào)用實例里的render方法來返回一個React元素。
3. 狀態(tài)管理
函數(shù)式組件沒有狀態(tài)管理喘落,類組件有狀態(tài)管理茵宪。
4. 使用場景
類組件沒有具體的要求。函數(shù)式組件一般是用在大型項目中來分割大組件(函數(shù)式組件不用創(chuàng)建實例瘦棋,所有更高效)稀火,一般情況下能用函數(shù)式組件就不用類組件,提升效率赌朋。
復(fù)制代碼
Set 和 Map有什么區(qū)別凰狞?
1、Map是鍵值對沛慢,Set是值得集合赡若,當(dāng)然鍵和值可以是任何得值
2、Map可以通過get方法獲取值团甲,而set不能因為它只有值
3逾冬、都能通過迭代器進行for...of 遍歷
4、Set的值是唯一的可以做數(shù)組去重躺苦,而Map由于沒有格式限制身腻,可以做數(shù)據(jù)存儲
復(fù)制代碼
說一說js是什么語言
JavaScript是一種直譯式腳本語言,是一種動態(tài)類型匹厘、弱類型嘀趟、基于原型的語言,內(nèi)置支持類型愈诚。它的解釋器被稱為JavaScript引擎去件,為瀏覽器的一部分,廣泛用于客戶端的腳本語言扰路,最早是在HTML(標準通用標記語言下的一個應(yīng)用)網(wǎng)頁上使用尤溜,用來給HTML網(wǎng)頁增加動態(tài)功能。
js語言是弱語言類型汗唱, 因此我們在項目開發(fā)中當(dāng)我們隨意更該某個變量的數(shù)據(jù)類型后
有可能會導(dǎo)致其他引用這個變量的方法中報錯等等宫莱。
復(fù)制代碼
說說瀏覽器緩存
緩存可以減少網(wǎng)絡(luò) IO 消耗,提高訪問速度哩罪。瀏覽器緩存是一種操作簡單授霸、效果顯著的前端性能優(yōu)化手段
很多時候巡验,大家傾向于將瀏覽器緩存簡單地理解為“HTTP 緩存”。
但事實上碘耳,瀏覽器緩存機制有四個方面显设,它們按照獲取資源時請求的優(yōu)先級依次排列如下:
Memory Cache
Service Worker Cache
HTTP Cache
Push Cache
緩存它又分為強緩存和協(xié)商緩存。優(yōu)先級較高的是強緩存辛辨,在命中強緩存失敗的情況下捕捂,才會走協(xié)商緩存
實現(xiàn)強緩存,過去我們一直用 expires斗搞。 當(dāng)服務(wù)器返回響應(yīng)時指攒,在 Response Headers 中將過期時間寫入 expires 字段,現(xiàn)在一般使用Cache-Control 兩者同時出現(xiàn)使用Cache-Control 協(xié)商緩存僻焚,Last-Modified 是一個時間戳允悦,如果我們啟用了協(xié)商緩存,它會在首次請求時隨著 Response Headers 返回:每次請求去判斷這個時間戳是否發(fā)生變化虑啤。 從而去決定你是304讀取緩存還是給你返回最新的數(shù)據(jù)
復(fù)制代碼
原型
構(gòu)造函數(shù)是一種特殊的方法隙弛,主要用來在創(chuàng)建對象時初始化對象。每個構(gòu)造函數(shù)都有prototype(原型)(箭頭函數(shù)以及Function.prototype.bind()沒有)屬性狞山,
這個prototype(原型)屬性是一個指針全闷,指向一個對象,這個對象的用途是包含特定類型的所有實例共享的
屬性和方法铣墨,即這個原型對象是用來給實例對象共享屬性和方法的室埋。每個實例對象的__proto__都指向這個
構(gòu)造函數(shù)/類的prototype屬性办绝。
面向?qū)ο蟮娜筇匦裕豪^承/多態(tài)/封裝
關(guān)于new操作符:
1. new執(zhí)行的函數(shù), 函數(shù)內(nèi)部默認生成了一個對象
2. 函數(shù)內(nèi)部的this默認指向了這個new生成的對象
3. new執(zhí)行函數(shù)生成的這個對象, 是函數(shù)的默認返回值
ES5例子:
function Person(obj) {
this.name = obj.name
this.age= obj.age
}
// 原型方法
Person.prototype.say = function() {
console.log('你好,', this.name )
}
// p為實例化對象伊约,new Person()這個操作稱為構(gòu)造函數(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={
//入口文件的配置項
entry:{},
//出口文件的配置項
output:{},
//模塊:例如解讀CSS,圖片如何轉(zhuǎn)換,壓縮
module:{},
//插件孕蝉,用于生產(chǎn)模版和各項功能
plugins:[],
//配置webpack開發(fā)服務(wù)功能
devServer:{}
}
簡單描述了一下這幾個屬性是干什么的屡律。
描述一下npm run dev / npm run build執(zhí)行的是哪些文件
通過配置proxyTable來達到開發(fā)環(huán)境跨域的問題,然后又可以擴展和他聊聊跨域的產(chǎn)生降淮,如何跨域
最后可以在聊聊webpack的優(yōu)化超埋,例如babel-loader的優(yōu)化,gzip壓縮等等
復(fù)制代碼
說一下vue3.0你了解多少?
<!-- 響應(yīng)式原理的改變 Vue3.x 使用Proxy取代 Vue2.x 版本的Object.defineProperty -->
<!-- 組件選項聲明方式Vue3.x 使用Composition API setup 是Vue3.x新增的一個選項佳鳖,他
是組件內(nèi)使用Composition API 的入口 -->
<!-- 模板語法變化slot具名插槽語法 自定義指令 v-model 升級 -->
<!-- 其它方面的更改Suspense支持Fragment(多個根節(jié)點) 和Protal (在dom其他部分渲染組建內(nèi)容)組件
針對一些特殊的場景做了處理霍殴。基于treeshaking優(yōu)化系吩,提供了更多的內(nèi)置功能来庭。 -->
復(fù)制代碼
你在工作終于到那些問題,解決方法是什么
經(jīng)常遇到的問題就是Cannot read property ‘prototype’ of undefined
解決辦法通過瀏覽器報錯提示代碼定位問題穿挨,解決問題
Vue項目中遇到視圖不更新月弛,方法不執(zhí)行肴盏,埋點不觸發(fā)等問題
一般解決方案查看瀏覽器報錯,查看代碼運行到那個階段未之行結(jié)束帽衙,閱讀源碼以及相關(guān)文檔等
然后舉出來最近開發(fā)的項目中遇到的算是兩個比較大的問題菜皂。
復(fù)制代碼
說一下data為什么是一個函數(shù)而不是一個對象?
JavaScript中的對象是引用類型的數(shù)據(jù),當(dāng)多個實例引用同一個對象時厉萝,只要一個實例對這個對象進行操作恍飘,其他實例中的數(shù)據(jù)也會發(fā)生變化。而在Vue中冀泻,我們更多的是想要復(fù)用組件常侣,那就需要每個組件都有自己的數(shù)據(jù),這樣組件之間才不會相互干擾弹渔。所以組件的數(shù)據(jù)不能寫成對象的形式胳施,而是要寫成函數(shù)的形式。數(shù)據(jù)以函數(shù)返回值的形式定義肢专,這樣當(dāng)我們每次復(fù)用組件的時候舞肆,就會返回一個新的data,也就是說每個組件都有自己的私有數(shù)據(jù)空間博杖,它們各自維護自己的數(shù)據(jù)椿胯,不會干擾其他組件的正常運行。
說一下常見的git操作
git branch 查看本地所有分支
git status 查看當(dāng)前狀態(tài)
git commit 提交
git branch -a 查看所有的分支
git branch -r 查看遠程所有分支
git commit -am "nit" 提交并且加注釋
git remote add origin git@192.168.1.119:ndshow
git push origin master 將文件給推到服務(wù)器上
git remote show origin 顯示遠程庫origin里的資源
git push origin master:develop
git push origin master:hb-dev 將本地庫與服務(wù)器上的庫進行關(guān)聯(lián)
git checkout --track origin/dev 切換到遠程dev分支
git branch -D master develop 刪除本地庫develop
git checkout -b dev 建立一個新的本地分支dev
git merge origin/dev 將分支dev與當(dāng)前分支進行合并
git checkout dev 切換到本地dev分支
git remote show 查看遠程庫
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] 刪除一個文件
git commit -a 提交當(dāng)前repos的所有的改變
git add [file name] 添加一個文件到git index
git commit -v 當(dāng)你用-v參數(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 強行移除修改后文件(從暫存區(qū)和工作區(qū)中刪除)
git diff --cached 或 $ git diff --staged 查看尚未提交的更新
git stash push 將文件給push到一個臨時空間中
git stash pop 將文件從臨時空間pop下來
webpack3和webpack4區(qū)別
1.mode
webpack增加了一個mode配置哩盲,只有兩種值development | production。對不同的環(huán)境他會啟用不同的配置狈醉。
2.CommonsChunkPlugin
CommonChunksPlugin已經(jīng)從webpack4中移除廉油。
可使用optimization.splitChunks進行模塊劃分(提取公用代碼)。
但是需要注意一個問題苗傅,默認配置只會對異步請求的模塊進行提取拆分抒线,如果要對entry進行拆分
需要設(shè)置optimization.splitChunks.chunks = 'all'。
3.webpack4使用MiniCssExtractPlugin取代ExtractTextWebpackPlugin渣慕。
4.代碼分割嘶炭。
使用動態(tài)import,而不是用system.import或者require.ensure
5.vue-loader逊桦。
使用vue-loader插件為.vue文件中的各部分使用相對應(yīng)的loader眨猎,比如css-loader等
6.UglifyJsPlugin
現(xiàn)在也不需要使用這個plugin了,只需要使用optimization.minimize為true就行强经,production mode下面自動為true
optimization.minimizer可以配置你自己的壓縮程序
復(fù)制代碼
New操作符做了什么事情?
1睡陪、首先創(chuàng)建了一個新對象
2、設(shè)置原型夕凝,將對象的原型設(shè)置為函數(shù)的prototype對象
3宝穗、讓函數(shù)的this指向這個對象户秤,執(zhí)行構(gòu)造函數(shù)的代碼(為這個新對象添加屬性)
4、判斷函數(shù)的返回值類型逮矛,如果是值類型鸡号,返回創(chuàng)建的對象。如果是引用類型须鼎,就返回這個引用類型的對象
復(fù)制代碼
JS閉包鲸伴,你了解多少?
應(yīng)該有面試官問過你:
- 什么是閉包晋控?
- 閉包有哪些實際運用場景汞窗?
- 閉包是如何產(chǎn)生的?
- 閉包產(chǎn)生的變量如何被回收赡译?
這些問題其實都可以被看作是同一個問題仲吏,那就是面試官在問你:你對JS閉包了解多少?
來總結(jié)一下我聽到過的答案蝌焚,盡量完全復(fù)原候選人面試的時候說的原話裹唆。
答案1:
就是一個function
里面return
了一個子函數(shù),子函數(shù)訪問了外面那個函數(shù)的變量只洒。
答案2:
for循環(huán)里面可以用閉包來解決問題许帐。
for(var i = 0; i < 10; i++){
setTimeout(()=>console.log(i),0)
}
// 控制臺輸出10遍10.
for(var i = 0; i < 10; i++){
(function(a){
setTimeout(()=>console.log(a),0)
})(i)
}
// 控制臺輸出0-9
復(fù)制代碼
答案3:
當(dāng)前作用域產(chǎn)產(chǎn)生了對父作用域的引用。
答案4:
不知道毕谴。是跟瀏覽器的垃圾回收機制有關(guān)嗎成畦?
開杠了。請問涝开,小伙伴的答案和以上的內(nèi)容有多少相似程度循帐?
其實,拿著這些問題好好想想忠寻,你就會發(fā)現(xiàn)這些問題都只是為了最終那一個問題惧浴。
閉包的底層實現(xiàn)原理
1. JS執(zhí)行上下文
我們都知道存和,我們手寫的js代碼是要經(jīng)過瀏覽器V8進行預(yù)編譯后才能真正的被執(zhí)行奕剃。例如變量提升、函數(shù)提升捐腿。舉個栗子纵朋。
// 栗子:
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"; // 此時變量a賦值,函數(shù)聲明被覆蓋
console.log(a); // "變量a"
a(); // a is not a function
復(fù)制代碼
那么問題來了茄袖。 請問是誰來執(zhí)行預(yù)編譯操作的操软?那這個誰又是在哪里進行預(yù)編譯的?
是的宪祥,你的疑惑沒有錯聂薪。js代碼運行需要一個運行環(huán)境家乘,那這個環(huán)境就是執(zhí)行上下文。 是的藏澳,js運行前的預(yù)編譯也是在這個環(huán)境中進行仁锯。
js執(zhí)行上下文分三種:
-
全局執(zhí)行上下文
: 代碼開始執(zhí)行時首先進入的環(huán)境。 -
函數(shù)執(zhí)行上下文
:函數(shù)調(diào)用時翔悠,會開始執(zhí)行函數(shù)中的代碼业崖。 -
eval執(zhí)行上下文
:不建議使用,可忽略蓄愁。
那么双炕,執(zhí)行上下文的周期,分為兩個階段:
-
創(chuàng)建階段
- 創(chuàng)建詞法環(huán)境
- 生成變量對象(
VO
)撮抓,建立作用域鏈妇斤、作用域鏈、作用域鏈(重要的事說三遍) - 確認
this
指向丹拯,并綁定this
-
執(zhí)行階段
趟济。這個階段進行變量賦值,函數(shù)引用及執(zhí)行代碼咽笼。
你現(xiàn)在猜猜看顷编,預(yù)編譯是發(fā)生在什么時候?
噢剑刑,我忘記說了媳纬,其實與編譯還有另一個稱呼:執(zhí)行期上下文
。
預(yù)編譯發(fā)生在函數(shù)執(zhí)行之前施掏。預(yù)編譯四部曲為:
- 創(chuàng)建
AO
對象 - 找形參和變量聲明钮惠,將變量和形參作為AO屬性名,值為
undefined
- 將實參和形參相統(tǒng)一
- 在函數(shù)體里找到函數(shù)聲明七芭,值賦予函數(shù)體素挽。最后程序輸出變量值的時候,就是從
AO
對象中拿狸驳。
所以预明,預(yù)編譯真正的結(jié)果是:
var AO = {
a = function a(){console.log("函數(shù)a");};
d = 'abc'
}
復(fù)制代碼
我們重新來。
1. 什么叫變量對象耙箍?
變量對象是 js
代碼在進入執(zhí)行上下文時撰糠,js
引擎在內(nèi)存中建立的一個對象,用來存放當(dāng)前執(zhí)行環(huán)境中的變量辩昆。
2. 變量對象(VO)的創(chuàng)建過程
變量對象的創(chuàng)建阅酪,是在執(zhí)行上下文創(chuàng)建階段,依次經(jīng)過以下三個過程:
-
創(chuàng)建
arguments
對象。對于函數(shù)執(zhí)行環(huán)境术辐,首先查詢是否有傳入的實參砚尽,如果有,則會將參數(shù)名是實參值組成的鍵值對放入
arguments
對象中辉词。否則尉辑,將參數(shù)名和undefined
組成的鍵值對放入arguments
對象中。
//舉個栗子
function bar(a, b, c) {
console.log(arguments); // [1, 2]
console.log(arguments[2]); // undefined
}
bar(1,2)
復(fù)制代碼
- 當(dāng)遇到同名的函數(shù)時较屿,后面的會覆蓋前面的隧魄。
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)建完成.后面的對之前的聲明進行了覆蓋隘蝎。**/
復(fù)制代碼
- 檢查當(dāng)前環(huán)境中的變量聲明并賦值為
undefined
购啄。當(dāng)遇到同名的函數(shù)聲明,為了避免函數(shù)被賦值為undefined
,會忽略此聲明
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í)行一下嘱么,你會發(fā)現(xiàn) a 打印結(jié)果仍舊是一個函數(shù)狮含,而 b 則是 undefined。**/
復(fù)制代碼
根據(jù)以上三個步驟曼振,對于變量提升也就知道是怎么回事了几迄。
3. 變量對象變?yōu)榛顒訉ο?/h5>
執(zhí)行上下文的第二個階段,稱為執(zhí)行階段冰评,在此時映胁,會進行變量賦值,函數(shù)引用并執(zhí)行其他代碼甲雅,此時解孙,變量對象變?yōu)榛顒訉ο蟆?/p>
我們還是舉上面的例子:
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)建變量對象
scopeChain: {}; // 作用域鏈
}
VO = {
argument: {...}; // 當(dāng)前為全局上下文,所以這個屬性值是空的
a: <a reference> // 函數(shù) a 的引用地址 b: undefiend // 見上文創(chuàng)建變量對象的第三步}
復(fù)制代碼
詞法作用域(Lexical scope
)
這里想說明妖枚,我們在函數(shù)執(zhí)行上下文中有變量廷臼,在全局執(zhí)行上下文中有變量。JavaScript
的一個復(fù)雜之處在于它如何查找變量绝页,如果在函數(shù)執(zhí)行上下文中找不到變量荠商,它將在調(diào)用上下文中尋找它,如果在它的調(diào)用上下文中沒有找到抒寂,就一直往上一級结啼,直到它在全局執(zhí)行上下文中查找為止掠剑。(如果最后找不到屈芜,它就是 undefined
)。
再來舉個栗子:
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í)行上下文中聲明了一個名為
createWarp
的變量井佑,并為其分配了一個函數(shù)定義属铁。其中第3-7行描述了其函數(shù)定義,并將函數(shù)定義存儲到那個變量(createWarp
)中躬翁。 - 第9行焦蘑。我們在全局執(zhí)行上下文中聲明了一個名為
sum
的新變量,暫時盒发,值為undefined
例嘱。 - 第9行。遇到
()
宁舰,表明需要執(zhí)行或調(diào)用一個函數(shù)拼卵。那么查找全局執(zhí)行上下文的內(nèi)存并查找名為createWarp
的變量。 明顯蛮艰,已經(jīng)在步驟2中創(chuàng)建完畢腋腮。接著,調(diào)用它壤蚜。 - 調(diào)用函數(shù)時即寡,回到第2行。創(chuàng)建一個新的
createWarp
執(zhí)行上下文袜刷。我們可以在createWarp
的執(zhí)行上下文中創(chuàng)建自有變量聪富。js
引擎createWarp
的上下文添加到調(diào)用堆棧(call stack
)。因為這個函數(shù)沒有參數(shù)著蟹,直接跳到它的主體部分. - 3 - 6 行善涨。我們有一個新的函數(shù)聲明,在
createWarp
執(zhí)行上下文中創(chuàng)建一個變量add
草则。add
只存在于createWarp
執(zhí)行上下文中, 其函數(shù)定義存儲在名為add
的自有變量中钢拧。 - 第7行,我們返回變量
add
的內(nèi)容炕横。js引擎查找一個名為add
的變量并找到它. 第4行和第5行括號之間的內(nèi)容構(gòu)成該函數(shù)定義源内。 -
createWarp
調(diào)用完畢,createWarp
執(zhí)行上下文將被銷毀份殿。add 變量也跟著被銷毀膜钓。 但add
函數(shù)定義仍然存在,因為它返回并賦值給了sum
變量卿嘲。 (ps:這才是閉包產(chǎn)生的變量存于內(nèi)存當(dāng)中的真相
) - 接下來就是簡單的執(zhí)行過程颂斜,不再贅述。拾枣。
- ……
- 代碼執(zhí)行完畢沃疮,全局執(zhí)行上下文被銷毀盒让。sum 和 result 也跟著被銷毀。
小結(jié)一下
現(xiàn)在司蔬,如果再讓你回答什么是閉包邑茄,你能答出多少?
其實俊啼,大家說的都對肺缕。不管是函數(shù)返回一個函數(shù),還是產(chǎn)生了外部作用域的引用授帕,都是有道理的同木。
所以,什么是閉包跛十?
- 解釋一下作用域鏈是如何產(chǎn)生的泉手。
- 解釋一下js執(zhí)行上下文的創(chuàng)建、執(zhí)行過程偶器。
- 解釋一下閉包所產(chǎn)生的變量放在哪了斩萌。
- 最后請把以上3點結(jié)合起來說給面試官聽邀泉。
深拷貝淺拷貝
淺拷貝:淺拷貝通過ES6新特性O(shè)bject.assign()或者通過擴展運算法...來達到淺拷貝的目的匾南,淺拷貝修改
副本麻献,不會影響原數(shù)據(jù)涨醋,但缺點是淺拷貝只能拷貝第一層的數(shù)據(jù)葛假,且都是值類型數(shù)據(jù)卦羡,如果有引用型數(shù)據(jù)窟社,修改
副本會影響原數(shù)據(jù)痊末。
深拷貝:通過利用JSON.parse(JSON.stringify())來實現(xiàn)深拷貝的目的唁盏,但利用JSON拷貝也是有缺點的内狸,
當(dāng)要拷貝的數(shù)據(jù)中含有undefined/function/symbol類型是無法進行拷貝的,當(dāng)然我們想項目開發(fā)中需要
深拷貝的數(shù)據(jù)一般不會含有以上三種類型厘擂,如有需要可以自己在封裝一個函數(shù)來實現(xiàn)昆淡。
復(fù)制代碼
說一下你對盒模型的理解?
CSS3中的盒模型有以下兩種:標準盒模型、IE盒模型
盒模型都是由四個部分組成的,分別是margin刽严、border昂灵、padding和content
標準盒模型和IE盒模型的區(qū)別在于設(shè)置width和height時, 所對應(yīng)的范圍不同
1、標準盒模型的width和height屬性的范圍只包含了content
2舞萄、IE盒模型的width和height屬性的范圍包含了border眨补、padding和content
可以通過修改元素的box-sizing屬性來改變元素的盒模型;
1倒脓、box-sizing:content-box表示標準盒模型(默認值)
2撑螺、box-sizing:border-box表示IE盒模型(怪異盒模型)
復(fù)制代碼
CDN的作用
CDN一般會用來托管Web資源(包括文本、圖片和腳本等)崎弃,可供下載的資源(媒體文件甘晤、軟件含潘、文檔等),應(yīng)用程序(門戶網(wǎng)站等)安皱。使用CDN來加速這些資源的訪問调鬓。
(1)在性能方面艇炎,引入CDN的作用在于:
- 用戶收到的內(nèi)容來自最近的數(shù)據(jù)中心酌伊,延遲更低,內(nèi)容加載更快
- 部分資源請求分配給了CDN缀踪,減少了服務(wù)器的負載
(2)在安全方面居砖,CDN有助于防御DDoS、MITM等網(wǎng)絡(luò)攻擊:
- 針對DDoS:通過監(jiān)控分析異常流量驴娃,限制其請求頻率
- 針對MITM:從源服務(wù)器到 CDN 節(jié)點到 ISP(Internet Service Provider)奏候,全鏈路 HTTPS 通信
除此之外,CDN作為一種基礎(chǔ)的云服務(wù)唇敞,同樣具有資源托管蔗草、按需擴展(能夠應(yīng)對流量高峰)等方面的優(yōu)勢。
代碼輸出結(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ù)制代碼
返回任意一個非 promise 的值都會被包裹成 promise 對象疆柔,因此這里的return new Error('error!!!')
也被包裹成了return Promise.resolve(new Error('error!!!'))
咒精,因此它會被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 => 像一個裝飾器昭抒,包裹mutations,使之可以異步炼杖。
5灭返、modules => 模塊化Vuex
1、Vuex中所有的狀態(tài)更新的唯一途徑都是mutation坤邪,異步操作通過 Action 來提交 mutation實現(xiàn)熙含,這樣可以方便地跟蹤每一個狀態(tài)的變化,從而能夠?qū)崿F(xiàn)一些工具幫助更好地了解我們的應(yīng)用艇纺。
2怎静、每個mutation執(zhí)行完成后都會對應(yīng)到一個新的狀態(tài)變更邮弹,這樣devtools就可以打個快照存下來,然后就可以實現(xiàn) time-travel 了蚓聘。如果mutation支持異步操作腌乡,就沒有辦法知道狀態(tài)是何時更新的,無法很好的進行狀態(tài)的追蹤夜牡,給調(diào)試帶來困難与纽。
復(fù)制代碼