摘要:引言半月刊第四期來啦,這段時間新增了道高頻面試題,今天就把最近半月匯總的面試題和部分答案發(fā)給大家,幫助大家查漏補缺,歡迎加群互相學習。更多更全的面試題和答案匯總在下面的項目中,點擊查看。
引言半月刊第四期來啦,這段時間 Daily-Interview-Question 新增了 14 道高頻面試題,今天就把最近半月匯總的面試題和部分答案發(fā)給大家,幫助大家查漏補缺,歡迎 加群 互相學習。
更多更全的面試題和答案匯總在下面的項目中,點擊查看。
項目地址:Daily-Interview-Question
第 40 題:在 Vue 中,子組件為何不可以修改父組件傳遞的 Prop如果修改了,Vue 是如何監(jiān)控到屬性的修改并給出警告的。
解析:
子組件為何不可以修改父組件傳遞的 Prop 單向數(shù)據(jù)流,易于監(jiān)測數(shù)據(jù)的流動,出現(xiàn)了錯誤可以更加迅速的定位到錯誤發(fā)生的位置。
如果修改了,Vue 是如何監(jiān)控到屬性的修改并給出警告的。
if (process.env.NODE_ENV !== "production") {
var hyphenatedKey = hyphenate(key);
if (isReservedAttribute(hyphenatedKey) ||
config.isReservedAttr(hyphenatedKey)) {
warn(
(""" + hyphenatedKey + "" is a reserved attribute and cannot be used as component prop."),
vm
);
}
defineReactive$$1(props, key, value, function () {
if (!isRoot && !isUpdatingChildComponent) {
warn(
"Avoid mutating a prop directly since the value will be " +
"overwritten whenever the parent component re-renders. " +
"Instead, use a data or computed property based on the prop"s " +
"value. Prop being mutated: "" + key + """,
vm
);
}
});
}
在initProps的時候,在defineReactive時通過判斷是否在開發(fā)環(huán)境,如果是開發(fā)環(huán)境,會在觸發(fā)set的時候判斷是否此key是否處于updatingChildren中被修改,如果不是,說明此修改來自子組件,觸發(fā)warning提示。
需要特別注意的是,當你從子組件修改的prop屬于基礎類型時會觸發(fā)提示。 這種情況下,你是無法修改父組件的數(shù)據(jù)源的, 因為基礎類型賦值時是值拷貝。你直接將另一個非基礎類型(Object, array)賦值到此key時也會觸發(fā)提示(但實際上不會影響父組件的數(shù)據(jù)源), 當你修改object的屬性時不會觸發(fā)提示,并且會修改父組件數(shù)據(jù)源的數(shù)據(jù)。
未完待續(xù),點擊查看更多細節(jié):第 40 題
第 41 題:下面代碼輸出什么var a = 10;
(function () {
console.log(a)
a = 5
console.log(window.a)
var a = 20;
console.log(a)
})()
解析:
依次輸出:undefined -> 10 -> 20
在立即執(zhí)行函數(shù)中,var a = 20; 語句定義了一個局部變量 a,由于js的變量聲明提升機制,局部變量a的聲明會被提升至立即執(zhí)行函數(shù)的函數(shù)體最上方,且由于這樣的提升并不包括賦值,因此第一條打印語句會打印undefined,最后一條語句會打印20。
由于變量聲明提升,a = 5; 這條語句執(zhí)行時,局部的變量a已經(jīng)聲明,因此它產(chǎn)生的效果是對局部的變量a賦值,此時window.a 依舊是最開始賦值的10。
未完待續(xù),點擊查看更多細節(jié):第 41題
第 42 題:實現(xiàn)一個 sleep 函數(shù)比如 sleep(1000) 意味著等待1000毫秒,可從 Promise、Generator、Async/Await 等角度實現(xiàn)。
解析:4 種方式
//Promise
const sleep = time => {
return new Promise(resolve => setTimeout(resolve,time))
}
sleep(1000).then(()=>{
console.log(1)
})
//Generator
function* sleepGenerator(time) {
yield new Promise(function(resolve,reject){
setTimeout(resolve,time);
})
}
sleepGenerator(1000).next().value.then(()=>{console.log(1)})
//async
function sleep(time) {
return new Promise(resolve => setTimeout(resolve,time))
}
async function output() {
let out = await sleep(1000);
console.log(1);
return out;
}
output();
//ES5
function sleep(callback,time) {
if(typeof callback === "function")
setTimeout(callback,time)
}
function output(){
console.log(1);
}
sleep(output,1000);
未完待續(xù),點擊查看更多細節(jié):第 42 題
第 43 題:使用 sort() 對數(shù)組 [3, 15, 8, 29, 102, 22] 進行排序,輸出結果解析:
sort 函數(shù),可以接收一個函數(shù),返回值是比較兩個數(shù)的相對順序的值
默認沒有函數(shù) 是按照 UTF-16 排序的,對于字母數(shù)字 你可以利用 ASCII 進行記憶
[3, 15, 8, 29, 102, 22].sort();
// [102, 15, 22, 29, 3, 8]
帶函數(shù)的比較
[3, 15, 8, 29, 102, 22].sort((a,b) => {return a - b});
返回值大于0 即a-b > 0 , a 和 b 交換位置
返回值小于0 即a-b < 0 , a 和 b 位置不變
返回值等于0 即a-b = 0 , a 和 b 位置不變
對于函數(shù)體返回 b-a 可以類比上面的返回值進行交換位置
未完待續(xù),點擊查看更多細節(jié):第 43 題
第 44 題:介紹 HTTPS 握手過程解析:
開始加密通信之前,客戶端和服務器首先必須建立連接和交換參數(shù),這個過程叫做握手(handshake)。
假定客戶端叫做愛麗絲,服務器叫做鮑勃,整個握手過程可以用下圖說明。
握手階段分成五步。
第一步,愛麗絲給出協(xié)議版本號、一個客戶端生成的隨機數(shù)(Client random),以及客戶端支持的加密方法。
第二步,鮑勃確認雙方使用的加密方法,并給出數(shù)字證書、以及一個服務器生成的隨機數(shù)(Server random)。
第三步,愛麗絲確認數(shù)字證書有效,然后生成一個新的隨機數(shù)(Premaster secret),并使用數(shù)字證書中的公鑰,加密這個隨機數(shù),發(fā)給鮑勃。
第四步,鮑勃使用自己的私鑰,獲取愛麗絲發(fā)來的隨機數(shù)(即Premaster secret)。
第五步,愛麗絲和鮑勃根據(jù)約定的加密方法,使用前面的三個隨機數(shù),生成"對話密鑰"(session key),用來加密接下來的整個對話過程。
參考:
圖解SSL/TLS協(xié)議
SSL/TLS協(xié)議運行機制的概述
未完待續(xù),點擊查看更多細節(jié):第 44 題
第 45 題:HTTPS 握手過程中,客戶端如何驗證證書的合法性解析:
1、首先什么是HTTP協(xié)議");
2、加密通信: 為了安全性,雙方可以使用對稱加密的方式key進行信息交流,但是這種方式對稱加密秘鑰也會被攔截,也不夠安全,進而還是存在被中間人攻擊風險; 于是人們又想出來另外一種方式,使用非對稱加密的方式;使用公鑰/私鑰加解密;通信方A發(fā)起通信并攜帶自己的公鑰,接收方B通過公鑰來加密對稱秘鑰;然后發(fā)送給發(fā)起方A;A通過私鑰解密;雙發(fā)接下來通過對稱秘鑰來進行加密通信;但是這種方式還是會存在一種安全性;中間人雖然不知道發(fā)起方A的私鑰,但是可以做到偷天換日,將攔截發(fā)起方的公鑰key;并將自己生成的一對公/私鑰的公鑰發(fā)送給B;接收方B并不知道公鑰已經(jīng)被偷偷換過;按照之前的流程,B通過公鑰加密自己生成的對稱加密秘鑰key2;發(fā)送給A; 這次通信再次被中間人攔截,盡管后面的通信,兩者還是用key2通信,但是中間人已經(jīng)掌握了Key2;可以進行輕松的加解密;還是存在被中間人攻擊風險;
3、解決困境:權威的證書頒發(fā)機構CA來解決;
3.1制作證書:作為服務端的A,首先把自己的公鑰key1發(fā)給證書頒發(fā)機構,向證書頒發(fā)機構進行申請證書;證書頒發(fā)機構有一套自己的公私鑰,CA通過自己的私鑰來加密key1,并且通過服務端網(wǎng)址等信息生成一個證書簽名,證書簽名同樣使用機構的私鑰進行加密;制作完成后,機構將證書發(fā)給A;
3.2校驗證書真?zhèn)危寒擝向服務端A發(fā)起請求通信的時候,A不再直接返回自己的公鑰,而是返回一個證書; 說明:各大瀏覽器和操作系統(tǒng)已經(jīng)維護了所有的權威證書機構的名稱和公鑰。B只需要知道是哪個權威機構發(fā)的證書,使用對應的機構公鑰,就可以解密出證書簽名;接下來,B使用同樣的規(guī)則,生成自己的證書簽名,如果兩個簽名是一致的,說明證書是有效的; 簽名驗證成功后,B就可以再次利用機構的公鑰,解密出A的公鑰key1;接下來的操作,就是和之前一樣的流程了;
3.3:中間人是否會攔截發(fā)送假證書到B呢? 因為證書的簽名是由服務器端網(wǎng)址等信息生成的,并且通過第三方機構的私鑰加密中間人無法篡改; 所以最關鍵的問題是證書簽名的真?zhèn)危?/p>
4、https主要的思想是在http基礎上增加了ssl安全層,即以上認證過程。
未完待續(xù),點擊查看更多細節(jié):第 45 題
第 46 題:輸出以下代碼執(zhí)行的結果并解釋為什么var obj = {
"2": 3,
"3": 4,
"length": 2,
"splice": Array.prototype.splice,
"push": Array.prototype.push
}
obj.push(1)
obj.push(2)
console.log(obj)
解析:
涉及知識點:
類數(shù)組(ArrayLike):
一組數(shù)據(jù),由數(shù)組來存,但是如果要對這組數(shù)據(jù)進行擴展,會影響到數(shù)組原型,ArrayLike的出現(xiàn)則提供了一個中間數(shù)據(jù)橋梁,ArrayLike有數(shù)組的特性, 但是對ArrayLike的擴展并不會影響到原生的數(shù)組。
push方法:
push 方法有意具有通用性。該方法和 call() 或 apply() 一起使用時,可應用在類似數(shù)組的對象上。push 方法根據(jù) length 屬性來決定從哪里開始插入給定的值。如果 length 不能被轉成一個數(shù)值,則插入的元素索引為 0,包括 length 不存在時。當 length 不存在時,將會創(chuàng)建它。 唯一的原生類數(shù)組(array-like)對象是 Strings,盡管如此,它們并不適用該方法,因為字符串是不可改變的。
對象轉數(shù)組的方式:
Array.from()、splice()、concat()等。
題分析: 這個obj中定義了兩個key值,分別為splice和push分別對應數(shù)組原型中的splice和push方法,因此這個obj可以調用數(shù)組中的push和splice方法,調用對象的push方法:push(1),因為此時obj中定義length為2,所以從數(shù)組中的第二項開始插入,也就是數(shù)組的第三項(下表為2的那一項),因為數(shù)組是從第0項開始的,這時已經(jīng)定義了下標為2和3這兩項,所以它會替換第三項也就是下標為2的值,第一次執(zhí)行push完,此時key為2的屬性值為1,同理:第二次執(zhí)行push方法,key為3的屬性值為2。此時的輸出結果就是:
Object(4) [empty × 2, 1, 2, splice: ?, push: ?]---->
[
2: 1,
3: 2,
length: 4,
push: ? push(),
splice: ? splice()
]
因為只是定義了2和3兩項,沒有定義0和1這兩項,所以前面會是empty。 如果講這道題改為:
var obj = {
"2": 3,
"3": 4,
"length": 0,
"splice": Array.prototype.splice,
"push": Array.prototype.push
}
obj.push(1)
obj.push(2)
console.log(obj)
此時的打印結果就是:
Object(2) [1, 2, 2: 3, 3: 4, splice: ?, push: ?]---->
[
0: 1,
1: 2,
2: 3,
3: 4,
length: 2,
push: ? push(),
splice: ? splice()
]
原理:此時length長度設置為0,push方法從第0項開始插入,所以填充了第0項的empty 至于為什么對象添加了splice屬性后并沒有調用就會變成類數(shù)組對象這個問題,這是控制臺中 DevTools 猜測類數(shù)組的一個方式: github.com/ChromeDevTo…
未完待續(xù),點擊查看更多細節(jié):第 46 題
第 47 題:雙向綁定和 vuex 是否沖突解析:
當在嚴格模式中使用 Vuex 時,在屬于 Vuex 的 state 上使用 v-model 會比較棘手:
<input v-model="obj.message">
假設這里的 obj 是在計算屬性中返回的一個屬于 Vuex store 的對象,在用戶輸入時,v-model 會試圖直接修改 obj.message。在嚴格模式中,由于這個修改不是在 mutation 函數(shù)中執(zhí)行的, 這里會拋出一個錯誤。
用“Vuex 的思維”去解決這個問題的方法是:給 中綁定 value,然后偵聽 input 或者 change 事件,在事件回調中調用 action:
<input :value="message" @input="updateMessage">
// ...
computed: {
...mapState({
message: state => state.obj.message
})
},
methods: {
updateMessage (e) {
this.$store.commit("updateMessage", e.target.value)
}
}
下面是 mutation 函數(shù):
// ...
mutations: {
updateMessage (state, message) {
state.obj.message = message
}
}
雙向綁定的計算屬性
必須承認,這樣做比簡單地使用“v-model + 局部狀態(tài)”要啰嗦得多,并且也損失了一些 v-model 中很有用的特性。另一個方法是使用帶有 setter 的雙向綁定計算屬性:
<input v-model="message">
// ...
computed: {
message: {
get () {
return this.$store.state.obj.message
},
set (value) {
this.$store.commit("updateMessage", value)
}
}
}
未完待續(xù),點擊查看更多細節(jié):第 47 題
第 48 題:call 和 apply 的區(qū)別是什么,哪個性能更好一些解析:
Function.prototype.apply和Function.prototype.call 的作用是一樣的,區(qū)別在于傳入?yún)?shù)的不同;
第一個參數(shù)都是,指定函數(shù)體內this的指向;
第二個參數(shù)開始不同,apply是傳入帶下標的集合,數(shù)組或者類數(shù)組,apply把它傳給函數(shù)作為參數(shù),call從第二個開始傳入的參數(shù)是不固定的,都會傳給函數(shù)作為參數(shù)。
call比apply的性能要好,平常可以多用call, call傳入?yún)?shù)的格式正是內部所需要的格式,參考 call和apply的性能對比
未完待續(xù),點擊查看更多細節(jié):第 48 題
第 49 題:為什么通常在發(fā)送數(shù)據(jù)埋點請求的時候使用的是 1x1 像素的透明 gif 圖片?解析:
能夠完成整個 HTTP 請求+響應(盡管不需要響應內容)
觸發(fā) GET 請求之后不需要獲取和處理數(shù)據(jù)、服務器也不需要發(fā)送數(shù)據(jù)
跨域友好
執(zhí)行過程無阻塞
相比 XMLHttpRequest 對象發(fā)送 GET 請求,性能上更好
GIF的最低合法體積最小(最小的BMP文件需要74個字節(jié),PNG需要67個字節(jié),而合法的GIF,只需要43個字節(jié))
不會阻塞頁面加載,影響用戶的體驗,只要new Image對象就好了;(排除JS/CSS文件資源方式上報)
未完待續(xù),點擊查看更多細節(jié):第 49 題
第 50 題:實現(xiàn) (5).add(3).minus(2) 功能。例: 5 + 3 - 2,結果為 6
解析:
Number.prototype.add = function(n) {
return this.valueOf() + n;
};
Number.prototype.minus = function(n) {
return this.valueOf() - n;
};
未完待續(xù),點擊查看更多細節(jié):第 50 題
第 51 題:Vue 的響應式原理中 Object.defineProperty 有什么缺陷?為什么在 Vue3.0 采用了 Proxy,拋棄了 Object.defineProperty?
解析:
Object.defineProperty本身有一定的監(jiān)控到數(shù)組下標變化的能力: Object.defineProperty本身是可以監(jiān)控到數(shù)組下標的變化的,但是在 Vue 中,從性能/體驗的性價比考慮,尤大大就棄用了這個特性。具體我們可以參考 《記一次思否問答的問題思考:Vue為什么不能檢測數(shù)組變動》這篇文章,文章底部配圖中有尤大大的嚴肅回復截圖; 下方的討論區(qū)也很值得大家下去看一看,有對于 for / forEach / for .. in .. 幾個循環(huán)方式的討論。
關于 Vue 3.0 的其他信息我們可以參考 尤大大發(fā)布的 Vue 3.0 新特性預覽PPT
直接通過數(shù)組的下標給數(shù)組設置值,不能實時響應。 為了解決這個問題,經(jīng)過vue內部處理后可以使用以下幾種方法來監(jiān)聽數(shù)組
push()
pop()
shift()
unshift()
splice()
sort()
reverse()
由于只針對了以上幾種方法進行了hack處理,所以其他數(shù)組的屬性也是檢測不到的,還是具有一定的局限性。
Object.defineProperty只能劫持對象的屬性,因此我們需要對每個對象的每個屬性進行遍歷。Vue 2.x里,是通過 遞歸 + 遍歷 data 對象來實現(xiàn)對數(shù)據(jù)的監(jiān)控的,如果屬性值也是對象那么需要深度遍歷,顯然如果能劫持一個完整的對象是才是更好的選擇。
而要取代它的Proxy有以下兩個優(yōu)點;
可以劫持整個對象,并返回一個新對象 有13種劫持操作
未完待續(xù),點擊查看更多細節(jié):第 51 題
第 52 題:怎么讓一個 div 水平垂直居中解析:
div.parent {
display: flex;
justify-content: center;
align-items: center;
}
div.parent {
position: relative;
}
div.child {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
}
/* 或者 */
div.child {
width: 50px;
height: 10px;
position: absolute;
top: 50%;
left: 50%;
margin-left: -25px;
margin-top: -5px;
}
/* 或 */
div.child {
width: 50px;
height: 10px;
position: absolute;
left: 0;
top: 0;
right: 0;
bottom: 0;
margin: auto;
}
div.parent {
display: grid;
}
div.child {
justify-self: center;
align-self: center;
}
div.parent { font-size: 0; text-align: center; &::before { content: ""; display: inline-block; width: 0; height: 100%; vertical-align: middle; } } div.parent{ display: inline-block; vertical-align: middle; }
未完待續(xù),點擊查看更多細節(jié):第 52 題
第 53 題:輸出以下代碼的執(zhí)行結果并解釋為什么var a = {n: 1};
var b = a;
a.x = a = {n: 2};
console.log(a.x)
console.log(b.x)
解析:
var a = {n: 1};
var b = a;
a.x = a = {n: 2};
a.x // --> undefined
b.x // --> {n: 2}
答案已經(jīng)寫上面了,這道題的關鍵在于
1、優(yōu)先級。.的優(yōu)先級高于=,所以先執(zhí)行a.x,堆內存中的{n: 1}就會變成{n: 1, x: undefined},改變之后相應的b.x也變化了,因為指向的是同一個對象。
2、賦值操作是從右到左,所以先執(zhí)行a = {n: 2},a的引用就被改變了,然后這個返回值又賦值給了a.x,需要注意的是這時候a.x是第一步中的{n: 1, x: undefined}那個對象,其實就是b.x,相當于b.x = {n: 2}
未完待續(xù),點擊查看更多細節(jié):第 53 題
進階系列文章匯總如下,覺得不錯點個 Star,歡迎 加群 互相學習。
github.com/yygmind/blo…
我是木易楊,公眾號「高級前端進階」作者,跟著我每周重點攻克一個前端面試重難點。接下來讓我?guī)阕哌M高級前端的世界,在進階的路上,共勉!
文章版權歸作者所有,未經(jīng)允許請勿轉載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/7349.html
摘要:最近的一次更新的變量有效,并且會作用于全部的引用的處理方式和相同,變量值輸出時根據(jù)之前最近的一次定義計算,每次引用最近的定義有效嵌套三種預編譯器的選擇器嵌套在使用上來說沒有任何區(qū)別,甚至連引用父級選擇器的標記也相同。 面試匯總一:2018大廠高級前端面試題匯總 高級面試:【半月刊】前端高頻面試題及答案匯總 css內容 響應式布局 當前主流的三種預編譯器比較 CSS預處理器用一種專門的...
摘要:手冊網(wǎng)超級有用的前端基礎技術面試問題收集前端面試題目及答案匯總史上最全前端面試題含答案常見前端面試題及答案經(jīng)典面試題及答案精選總結前端面試過程中最容易出現(xiàn)的問題前端面試題整理騰訊前端面試經(jīng)驗前端基礎面試題部分最新前端面試題攻略前端面試前端入 手冊網(wǎng):http://www.shouce.ren/post/index 超級有用的前端基礎技術面試問題收集:http://www.codec...
摘要:手冊網(wǎng)超級有用的前端基礎技術面試問題收集前端面試題目及答案匯總史上最全前端面試題含答案常見前端面試題及答案經(jīng)典面試題及答案精選總結前端面試過程中最容易出現(xiàn)的問題前端面試題整理騰訊前端面試經(jīng)驗前端基礎面試題部分最新前端面試題攻略前端面試前端入 手冊網(wǎng):http://www.shouce.ren/post/index 超級有用的前端基礎技術面試問題收集:http://www.codec...
閱讀 3218·2021-11-12 10:36
閱讀 1279·2019-08-30 15:56
閱讀 2447·2019-08-30 11:26
閱讀 558·2019-08-29 13:00
閱讀 3613·2019-08-28 18:08
閱讀 2753·2019-08-26 17:18
閱讀 1901·2019-08-26 13:26
閱讀 2437·2019-08-26 11:39