更新:謝謝你們的支持,最近折騰了一個博客官網出來,方便你們系統閱讀,後續會有更多內容和更多優化,猛戳這裏查看html
------ 如下是正文 ------前端
半月刊第三期到來,這段時間 Daily-Interview-Question 新增了 15 道高頻面試題,今天就把最近半月彙總的面試題和部分答案發給你們,幫助你們查漏補缺。html5
更多更全的面試題和答案在下面的項目地址中,點擊查看。node
項目地址:Daily-Interview-Questionwebpack
關於微任務和宏任務在瀏覽器的執行順序是這樣的:git
如此循環往復下去github
瀏覽器的 task(宏任務)執行順序在 html#event-loops 裏面有講就不翻譯了 常見的 task(宏任務) 好比:setTimeout、setInterval、script(總體代碼)、 I/O 操做、UI 渲染等。 常見的 micro-task 好比: new Promise().then(回調)、MutationObserver(html5新特性) 等。web
Node的事件循環是libuv實現的,引用一張官網的圖:面試
大致的task(宏任務)執行順序是這樣的:chrome
微任務和宏任務在Node的執行順序
Node 10之前:
Node 11之後: 和瀏覽器的行爲統一了,都是每執行一個宏任務就執行完微任務隊列。
未完待續,點擊查看更多細節:第25題:瀏覽器和Node 事件循環的區別
可從IIFE、AMD、CMD、CommonJS、UMD、webpack(require.ensure)、ES Module、<script type="module">
這幾個角度考慮。
解答:
模塊化主要是用來抽離公共代碼,隔離做用域,避免變量衝突等。
IIFE: 使用自執行函數來編寫模塊化,特色:在一個單獨的函數做用域中執行代碼,避免變量衝突。
(function(){
return {
data:[]
}
})()
複製代碼
AMD: 使用requireJS 來編寫模塊化,特色:依賴必須提早聲明好。
define('./index.js',function(code){
// code 就是index.js 返回的內容
})
複製代碼
CMD: 使用seaJS 來編寫模塊化,特色:支持動態引入依賴文件。
define(function(require, exports, module) {
var indexCode = require('./index.js');
});
複製代碼
CommonJS: nodejs 中自帶的模塊化。
var fs = require('fs');
複製代碼
UMD:兼容AMD,CommonJS 模塊化語法。
webpack(require.ensure):webpack 2.x 版本中的代碼分割。
ES Modules: ES6 引入的模塊化,支持import 來引入另外一個 js 。
import a from 'a';
複製代碼
未完待續,點擊查看更多細節:第26 題: 前端中的模塊化開發
在ES5中,頂層對象的屬性和全局變量是等價的,var 命令和 function 命令聲明的全局變量,天然也是頂層對象。
var a = 12;
function f(){};
console.log(window.a); // 12
console.log(window.f); // f(){}
複製代碼
但ES6規定,var 命令和 function 命令聲明的全局變量,依舊是頂層對象的屬性,但 let命令、const命令、class命令聲明的全局變量,不屬於頂層對象的屬性。
let aa = 1;
const bb = 2;
console.log(window.aa); // undefined
console.log(window.bb); // undefined
複製代碼
在哪裏?怎麼獲取?經過在設置斷點,看看瀏覽器是怎麼處理的:
經過上圖也能夠看到,在全局做用域中,用 let 和 const 聲明的全局變量並無在全局對象中,只是一個塊級做用域(Script)中
怎麼獲取?在定義變量的塊級做用域中就能獲取啊,既然不屬於頂層對象,那就不加 window(global)唄。
let aa = 1;
const bb = 2;
console.log(aa); // 1
console.log(bb); // 2
複製代碼
未完待續,點擊查看更多細節:第27題:關於 const 和 let 聲明的變量不在 window 上
一、首先token不是防止XSS的,而是爲了防止CSRF的; 二、CSRF攻擊的緣由是瀏覽器會自動帶上cookie,而瀏覽器不會自動帶上token
未完待續,點擊查看更多細節:第28題:cookie 和 token 都存放在 header 中,爲何不會劫持 token?
VM 主要作了兩件微小的事情:
一、M 到 V 實現
作到這件事的第一步是造成相似於:
// template
var tpl = '<p>{{ text }}</p>';
// data
var data = {
text: 'This is some text'
};
// magic process
template(tpl, data); // '<p>This is some text</p>'
複製代碼
中間的 magic process 是模板引擎所作的事情,已經有很是多種模板引擎可供選擇
固然你比較喜歡造輪子的話也能夠本身實現一個
不管是 Angular 的 $scope,React 的 state 仍是 Vue 的 data 都提供了一個較爲核心的 model 對象用來保存模型的狀態;它們的模板引擎稍有差異,不過大致思路類似;拿到渲染後的 string 接下來作什麼不言而喻了(中間還有不少處理,例如利用 model 的 diff 來最小量更新 view )。
可是僅僅是這樣並不夠,咱們須要知道何時來更新 view( 即 render ),通常來講主要的 VM 作了如下幾種選擇:
其中初始化拿到 model 對象而後 render 沒什麼好講的;model 被修改的時候如何監聽屬性的改變是一個問題,目前有如下幾種思路:
知道了觸發 render 的時機以及如何 render,一個簡單的 M 到 V 映射就實現了。
二、V 到 M 實現
從 V 到 M 主要由兩類( 雖然本質上都是監聽 DOM )構成,一類是用戶自定義的 listener, 一類是 VM 自動處理的含有 value 屬性元素的 listener
第一類相似於你在 Vue 裏用 v-on 時綁定的那樣,VM 在實例化得時候能夠將全部用戶自定義的 listener 一次性代理到根元素上,這些 listener 能夠訪問到你的 model 對象,這樣你就能夠在 listener 中改變 model
第二類相似於對含有 v-model 與 value 元素的自動處理,咱們指望的是例如在一個輸入框內
<input type="text" v-model="message" />
複製代碼
輸入值,那麼我與之對應的 model 屬性 message 也會隨之改變,至關於 VM 作了一個默認的 listener,它會監聽這些元素的改變而後自動改變 model,具體如何實現相信你也明白了
未完待續,點擊查看更多細節:第29題
請把兩個數組 ['A1', 'A2', 'B1', 'B2', 'C1', 'C2', 'D1', 'D2'] 和 ['A', 'B', 'C', 'D'],合併爲 ['A1', 'A2', 'A', 'B1', 'B2', 'B', 'C1', 'C2', 'C', 'D1', 'D2', 'D']。
解法:
let a1 = ['A1', 'A2', 'B1', 'B2', 'C1', 'C2', 'D1', 'D2']
let a2 = ['A', 'B', 'C', 'D'].map((item) => {
return item + 3
})
let a3 = [...a1, ...a2].sort().map((item) => {
if(item.includes('3')){
return item.split('')[0]
}
return item
})
複製代碼
未完待續,點擊查看更多細節: 第 30 題
for (var i = 0; i< 10; i++){
setTimeout(() => {
console.log(i);
}, 1000)
}
複製代碼
解法1:
for (var i = 0; i< 10; i++){
setTimeout((i) => {
console.log(i);
}, 1000,i)
}
複製代碼
解法2:
for (var i = 0; i< 10; i++){
((i) => {
setTimeout(() => {
console.log(i);
}, 1000)
})(i)
}
複製代碼
解法3:
for (let i = 0; i< 10; i++){
setTimeout(() => {
console.log(i);
}, 1000)
}
複製代碼
未完待續,點擊查看更多細節:第 31 題
採用尤大大的回答:
1. 原生 DOM 操做 vs. 經過框架封裝操做。
這是一個性能 vs. 可維護性的取捨。框架的意義在於爲你掩蓋底層的 DOM 操做,讓你用更聲明式的方式來描述你的目的,從而讓你的代碼更容易維護。沒有任何框架能夠比純手動的優化 DOM 操做更快,由於框架的 DOM 操做層須要應對任何上層 API 可能產生的操做,它的實現必須是普適的。針對任何一個 benchmark,我均可以寫出比任何框架更快的手動優化,可是那有什麼意義呢?在構建一個實際應用的時候,你難道爲每個地方都去作手動優化嗎?出於可維護性的考慮,這顯然不可能。框架給你的保證是,你在不須要手動優化的狀況下,我依然能夠給你提供過得去的性能。
2. 對 React 的 Virtual DOM 的誤解。
React 歷來沒有說過 「React 比原生操做 DOM 快」。React 的基本思惟模式是每次有變更就整個從新渲染整個應用。若是沒有 Virtual DOM,簡單來想就是直接重置 innerHTML。不少人都沒有意識到,在一個大型列表全部數據都變了的狀況下,重置 innerHTML 實際上是一個還算合理的操做... 真正的問題是在 「所有從新渲染」 的思惟模式下,即便只有一行數據變了,它也須要重置整個 innerHTML,這時候顯然就有大量的浪費。
咱們能夠比較一下 innerHTML vs. Virtual DOM 的重繪性能消耗:
Virtual DOM render + diff 顯然比渲染 html 字符串要慢,可是!它依然是純 js 層面的計算,比起後面的 DOM 操做來講,依然便宜了太多。能夠看到,innerHTML 的總計算量無論是 js 計算仍是 DOM 操做都是和整個界面的大小相關,但 Virtual DOM 的計算量裏面,只有 js 計算和界面大小相關,DOM 操做是和數據的變更量相關的。前面說了,和 DOM 操做比起來,js 計算是極其便宜的。這纔是爲何要有 Virtual DOM:它保證了 1)無論你的數據變化多少,每次重繪的性能均可以接受;2) 你依然能夠用相似 innerHTML 的思路去寫你的應用。
3. 性能比較也要看場合
在比較性能的時候,要分清楚初始渲染、小量數據更新、大量數據更新這些不一樣的場合。Virtual DOM、髒檢查 MVVM、數據收集 MVVM 在不一樣場合各有不一樣的表現和不一樣的優化需求。Virtual DOM 爲了提高小量數據更新時的性能,也須要針對性的優化,好比 shouldComponentUpdate 或是 immutable data。
不要天真地覺得 Virtual DOM 就是快,diff 不是免費的,batching 麼 MVVM 也能作,並且最終 patch 的時候還不是要用原生 API。在我看來 Virtual DOM 真正的價值歷來都不是性能,而是它 1) 爲函數式的 UI 編程方式打開了大門;2) 能夠渲染到 DOM 之外的 backend,好比 ReactNative。
未完待續,點擊查看更多細節:第 32 題
var b = 10;
(function b(){
b = 20;
console.log(b);
})();
複製代碼
解答:
實際上,有點相似於如下代碼,但不徹底相同,由於使用const無論在什麼模式下,都會TypeError類型的錯誤
const foo = function () {
foo = 10;
console.log(foo)
}
(foo)() // Uncaught TypeError: Assignment to constant variable.
複製代碼
b 函數是一個至關於用const定義的常量,內部沒法進行從新賦值,若是在嚴格模式下,會報錯"Uncaught TypeError: Assignment to constant variable." 例以下面的:
var b = 10;
(function b() {
'use strict'
b = 20;
console.log(b)
})() // "Uncaught TypeError: Assignment to constant variable."
複製代碼
未完待續,點擊查看更多細節:第 33 題
var b = 10;
(function b(){
b = 20;
console.log(b);
})();
複製代碼
解法:
未完待續,點擊查看更多細節:第 34 題
能夠分紅 Service Worker、Memory Cache、Disk Cache 和 Push Cache,那請求的時候 from memory cache 和 from disk cache 的依據是什麼,哪些數據何時存放在 Memory Cache 和 Disk Cache中?
解答:
總的來講:
注意:以上回答所有基於chrome瀏覽器
未完待續,點擊查看更多細節:第 35 題
迭代的實現:
let arr = [1, 2, [3, 4, 5, [6, 7], 8], 9, 10, [11, [12, 13]]]
const flatten = function (arr) {
while (arr.some(item => Array.isArray(item))) {
arr = [].concat(...arr)
}
return arr
}
console.log(flatten(arr))
複製代碼
遞歸的實現(ES6簡寫):
const flatten = array => array.reduce((acc, cur) => (Array.isArray(cur) ? [...acc, ...flatten(cur)] : [...acc, cur]), [])
複製代碼
未完待續,點擊查看更多細節:第 36 題
歡迎在 Issue 區留下你的答案。
var a = ?;
if(a == 1 && a == 2 && a == 3){
console.log(1);
}
複製代碼
解法1:利用 toString
let a = {
i: 1,
toString () {
return a.i++
}
}
if(a == 1 && a == 2 && a == 3) {
console.log(1);
}
複製代碼
解法2:利用 valueOf
let a = {
i: 1,
valueOf () {
return a.i++
}
}
if(a == 1 && a == 2 && a == 3) {
console.log(1);
}
複製代碼
解法3:數組這個就有點妖了
var a = [1,2,3];
a.join = a.shift;
if(a == 1 && a == 2 && a == 3) {
console.log(1);
}
複製代碼
解法4:ES6的symbol
let a = {
[Symbol.toPrimitive]: (i => () => ++i) (0)
};
if(a == 1 && a == 2 && a == 3) {
console.log(1);
}
複製代碼
解法5:Object.defineProperty
Object.defineProperty(window, 'a', {
get: function() {
return this.value = this.value ? (this.value += 1) : 1;
}
});
if(a == 1 && a == 2 && a == 3) {
console.log(1);
}
複製代碼
未完待續,點擊查看更多細節:第 38 題
BFC是CSS佈局的一個概念,是一塊獨立的渲染區域,是一個環境,裏面的元素不會影響到外部的元素 。
如何生成BFC:(即脫離文檔流)
BFC佈局規則:
1.內部的Box會在垂直方向,一個接一個地放置。
2.屬於同一個BFC的兩個相鄰的Box的margin會發生重疊
3.BFC就是頁面上的一個隔離的獨立容器,容器裏面的子元素不會影響到外面的元素。反之也如此, 文字環繞效果,設置float
4.BFC的區域不會與float box重疊。
5.計算BFC的高度,浮動元素也參與計算
BFC做用:
未完待續,點擊查看更多細節:第 39 題
進階系列文章彙總以下,內有優質前端資料,以爲不錯點個star。
我是木易楊,公衆號「高級前端進階」做者,跟着我每週重點攻克一個前端面試重難點。接下來讓我帶你走進高級前端的世界,在進階的路上,共勉!