社招中級(jí)前端筆試面試題總結(jié)-答案及拓展,前端筆試

最近看到有一篇文章總結(jié)了一些前端的面試題,面向的對(duì)象應(yīng)該是社招中初、中級(jí)的前端,感覺(jué)有一定的參考價(jià)值,因此開一個(gè)帖子嘗試解答這些問(wèn)題,順便當(dāng)做自己的面試題積累。愛(ài)掏網(wǎng) - it200.com

原文鏈接戳這里

JavaScript基礎(chǔ)

在網(wǎng)上找到一篇文章,里面有一道面試題,考察了包括變量定義提升、this指針指向、運(yùn)算符優(yōu)先級(jí)、原型、繼承、全局變量污染、對(duì)象屬性及原型屬性優(yōu)先級(jí)等許多知識(shí)點(diǎn),而就其中聲明提前相關(guān)的知識(shí),我覺(jué)得也十分有參考價(jià)值:

function Foo() {
 getName = function () { alert (1); };
 return this;
}
Foo.getName = function () { alert (2);};
Foo.prototype.getName = function () { alert (3);};
var getName = function () { alert (4);};
function getName() { alert (5);}

// 請(qǐng)寫出以下輸出結(jié)果:
Foo.getName();
getName(); // 聲明提前
Foo().getName();
getName();
new Foo.getName();
new Foo().getName();
new new Foo().getName();
復(fù)制代碼

這道題的答案是:2、4、1、1、2、3、3。愛(ài)掏網(wǎng) - it200.com

這里考察聲明提前的題目在代碼中已經(jīng)標(biāo)出,這里聲明getName方法的兩個(gè)語(yǔ)句:

var getName = function () { alert (4) };
function getName() { alert (5) }
復(fù)制代碼

實(shí)際上在解析的時(shí)候是這樣的順序:

function getName() { alert (5) }
var getName;
getName = function () { alert (4) };
復(fù)制代碼

如果我們?cè)诖a中間再加兩個(gè)斷點(diǎn):

getName(); // 5 var getName = function () { alert (4) };
getName(); // 4 function getName() { alert (5) }
復(fù)制代碼

在第一次getName時(shí),function的聲明和var的聲明都被提前到了第一次getName的前面,而getName的賦值操作并不會(huì)提前,單純使用var的聲明也不會(huì)覆蓋function所定義的變量,因此第一次getName輸出的是function聲明的5; 而第二次getName則是發(fā)生在賦值語(yǔ)句的后面,因此輸出的結(jié)果是4,所以實(shí)際代碼的執(zhí)行順序是這樣:

function getName() { alert (5) }
var getName;
getName(); // 5
getName = function () { alert (4) };
getName(); // 4 復(fù)制代碼

localStorage,sessionStorage和cookie的區(qū)別

共同點(diǎn):都是保存在瀏覽器端、僅同源可用的存儲(chǔ)方式

  1. 數(shù)據(jù)存儲(chǔ)方面
  • cookie數(shù)據(jù)始終在同源的http請(qǐng)求中攜帶(即使不需要),即cookie在瀏覽器和服務(wù)器間來(lái)回傳遞。愛(ài)掏網(wǎng) - it200.comcookie數(shù)據(jù)還有路徑(path)的概念,可以限制cookie只屬于某個(gè)路徑下
  • sessionStorage和localStorage不會(huì)自動(dòng)把數(shù)據(jù)發(fā)送給服務(wù)器,僅在本地保存。愛(ài)掏網(wǎng) - it200.com
  1. 存儲(chǔ)數(shù)據(jù)大小
  • 存儲(chǔ)大小限制也不同,cookie數(shù)據(jù)不能超過(guò)4K,同時(shí)因?yàn)槊看蝖ttp請(qǐng)求都會(huì)攜帶cookie、所以cookie只適合保存很小的數(shù)據(jù),如會(huì)話標(biāo)識(shí)。愛(ài)掏網(wǎng) - it200.com
  • sessionStorage和localStorage雖然也有存儲(chǔ)大小的限制,但比cookie大得多,可以達(dá)到5M或更大
  1. 數(shù)據(jù)存儲(chǔ)有效期
  • sessionStorage:僅在當(dāng)前瀏覽器窗口關(guān)閉之前有效;
  • localStorage:始終有效,窗口或?yàn)g覽器關(guān)閉也一直保存,本地存儲(chǔ),因此用作持久數(shù)據(jù);
  • cookie:只在設(shè)置的cookie過(guò)期時(shí)間之前有效,即使窗口關(guān)閉或?yàn)g覽器關(guān)閉
  1. 作用域不同
  • sessionStorage不在不同的瀏覽器窗口中共享,即使是同一個(gè)頁(yè)面;
  • localstorage在所有同源窗口中都是共享的;也就是說(shuō)只要瀏覽器不關(guān)閉,數(shù)據(jù)仍然存在
  • cookie: 也是在所有同源窗口中都是共享的.也就是說(shuō)只要瀏覽器不關(guān)閉,數(shù)據(jù)仍然存在

不久我寫了一個(gè)帖子,對(duì)同源策略及各種跨域的方式進(jìn)行了總結(jié):什么是跨域,為什么瀏覽器會(huì)禁止跨域,及其引起的發(fā)散性學(xué)習(xí)

Promise是ES6加入的新特性,用于更合理的解決異步編程問(wèn)題,關(guān)于用法阮一峰老師在ECMAScript 6 入門中作出了詳細(xì)的說(shuō)明,在此就不重復(fù)了。愛(ài)掏網(wǎng) - it200.com

30分鐘,讓你徹底明白Promise原理

上面這篇文章則是對(duì)Promise的原理進(jìn)行的詳細(xì)的說(shuō)明,在這里,我提取最簡(jiǎn)單的Promise實(shí)現(xiàn)方式來(lái)對(duì)Promise的原理進(jìn)行說(shuō)明:

function Promise(fn) {
 var value = null,
 callbacks = []; // callbacks為數(shù)組,因?yàn)榭赡芡瑫r(shí)有很多個(gè)回調(diào) this.then = function (onFulfilled) {
 callbacks.push(onFulfilled);
 };

 function resolve(value) {
 callbacks.forEach(function (callback) {
 callback(value);
 });
 }

 fn(resolve);
}
復(fù)制代碼

首先,then里面聲明的單個(gè)或多個(gè)函數(shù),將被推入callbacks列表,在Promise實(shí)例調(diào)用resolve方法時(shí)遍歷調(diào)用,并傳入resolve方法中傳入的參數(shù)值。愛(ài)掏網(wǎng) - it200.com

以下,使用一個(gè)簡(jiǎn)單的例子來(lái)對(duì)Promise的執(zhí)行流程進(jìn)行分析:

functionm func () {
	return new Promise(function (resolve) {
		setTimeout(function () {
			resolve('complete')
		}, 3000);
	})
}

func().then(function (res) {
	console.log(res); // complete
})
復(fù)制代碼

func函數(shù)的定義是返回了一個(gè)Promise實(shí)例,聲明實(shí)例時(shí)傳入的回調(diào)函數(shù)加入了一個(gè)resolve參數(shù)(這個(gè)resolve參數(shù)在Promise中的fn(resolve)定義中獲取resolve的函數(shù)實(shí)體),回調(diào)中執(zhí)行了一個(gè)異步操作,在異步操作完成的回調(diào)中執(zhí)行了resolve函數(shù)。愛(ài)掏網(wǎng) - it200.com

再看執(zhí)行步驟,func函數(shù)返回了一個(gè)Promise實(shí)例,實(shí)例則可以執(zhí)行Promise構(gòu)造函數(shù)中定義的then方法,then方法中傳入的回調(diào)則會(huì)在resolve(即異步操作完成后)執(zhí)行,由此實(shí)現(xiàn)了通過(guò)then方法執(zhí)行異步操作完成后回調(diào)的功能。愛(ài)掏網(wǎng) - it200.com

原文中貼出的文章具有很大參考價(jià)值,先貼個(gè)鏈接:詳解JavaScript中的Event Loop(事件循環(huán))機(jī)制。愛(ài)掏網(wǎng) - it200.com

JavaScript是一種單線程、非阻塞的語(yǔ)言,這是由于它當(dāng)初的設(shè)計(jì)就是用于和瀏覽器交互的:

  • 單線程:JavaScript設(shè)計(jì)為單線程的原因是,最開始它最大的作用就是和DOM進(jìn)行交互,試想一下,如果JavaScript是多線程的,那么當(dāng)兩個(gè)線程同時(shí)對(duì)DOM進(jìn)行一項(xiàng)操作,例如一個(gè)向其添加事件,而另一個(gè)刪除了這個(gè)DOM,此時(shí)該如何處理呢?因此,為了保證不會(huì) 發(fā)生類似于這個(gè)例子中的情景,JavaScript選擇只用一個(gè)主線程來(lái)執(zhí)行代碼,這樣就保證了程序執(zhí)行的一致性。愛(ài)掏網(wǎng) - it200.com
  • 非阻塞:當(dāng)代碼需要進(jìn)行一項(xiàng)異步任務(wù)(無(wú)法立刻返回結(jié)果,需要花一定時(shí)間才能返回的任務(wù),如I/O事件)的時(shí)候,主線程會(huì)掛起(pending)這個(gè)任務(wù),然后在異步任務(wù)返回結(jié)果的時(shí)候再根據(jù)一定規(guī)則去執(zhí)行相應(yīng)的回調(diào)。愛(ài)掏網(wǎng) - it200.comJavaScript實(shí)現(xiàn)異步操作的方法就是使用Event Loop。愛(ài)掏網(wǎng) - it200.com
setTimeout(function () {
 console.log(1);
});

new Promise(function(resolve,reject){
 console.log(2)
 resolve(3)
}).then(function(val){
 console.log(val);
})
復(fù)制代碼

下面通過(guò)一段代碼來(lái)分析這個(gè)問(wèn)題,首先setTimeoutPromise中的then回調(diào)都是異步方法,而new Promise則是一個(gè)同步操作,所以這段代碼應(yīng)該首先會(huì)立即輸出2JavaScript將異步方法分為了marco task(宏任務(wù):包括setTimeoutsetInterval等)和micro task(微任務(wù):包括new Promise等),在JavaScript的執(zhí)行棧中,如果同時(shí)存在到期的宏任務(wù)和微任務(wù),則會(huì)將微任務(wù)先全部執(zhí)行,再執(zhí)行第一個(gè)宏任務(wù),因此,兩個(gè)異步操作中then的回調(diào)會(huì)率先執(zhí)行,然后才執(zhí)行setTimeout的回調(diào),因此會(huì)依次輸出3、1,所以最終輸出的結(jié)果就是2、3、1。愛(ài)掏網(wǎng) - it200.com

這個(gè)問(wèn)題阮一峰老師在ECMAScript 6 入門中的let 和 const 命令章節(jié)對(duì)這個(gè)問(wèn)題作出了詳細(xì)的說(shuō)明,下面提取一些我認(rèn)為關(guān)鍵的點(diǎn)進(jìn)行講解。愛(ài)掏網(wǎng) - it200.com

ES6引入了使用{}包裹的代碼區(qū)域作為塊級(jí)作用域的聲明方式,其效果與ES5中function聲明的函數(shù)所生成的函數(shù)作用域具有相同的效果,作用域外部不能訪問(wèn)作用域內(nèi)部聲明的函數(shù)或變量,這樣的聲明在ES6中對(duì)于包括for () {}if () {}等大括號(hào)包裹的代碼塊中都會(huì)生效,生成一個(gè)單獨(dú)的作用域。愛(ài)掏網(wǎng) - it200.com

ES6新增的let聲明變量的方式相比var具有以下幾個(gè)重要特點(diǎn):

  • let聲明的變量只在作用域內(nèi)有效,如下方代碼,if聲明生成了一個(gè)塊級(jí)作用域,在這個(gè)作用域內(nèi)聲明的變量在作用域外部無(wú)法訪問(wèn),假如訪問(wèn)會(huì)產(chǎn)生錯(cuò)誤:
if (true) {
	let me = 'handsome boy';
}
console.log(me); // ReferenceError 復(fù)制代碼
  • let聲明的變量與var不同,不會(huì)產(chǎn)生變量提升,如下方代碼,在聲明之前輸出代碼,會(huì)產(chǎn)生錯(cuò)誤:
// var 的情況 console.log(foo); // 輸出undefined var foo = 2;

// let 的情況 console.log(bar); // ReferenceError let bar = 2;
復(fù)制代碼
  • let的聲明方式不允許重復(fù)聲明,如重復(fù)聲明會(huì)報(bào)錯(cuò),而var聲明變量時(shí),后聲明的語(yǔ)句會(huì)對(duì)先聲明的語(yǔ)句進(jìn)行覆蓋:
// 報(bào)錯(cuò) function func() {
 let a = 10;
 var a = 1;
}

// 報(bào)錯(cuò) function func() {
 let a = 10;
 let a = 1;
}
復(fù)制代碼
  • 只要塊級(jí)作用域內(nèi)存在let命令,它所聲明的變量就“綁定”(binding)這個(gè)區(qū)域,不再受外部的影響,這個(gè)特性稱為暫時(shí)性死區(qū)愛(ài)掏網(wǎng) - it200.com
var tmp = 123;

if (true) {
 tmp = 'abc'; // ReferenceError let tmp;
}
復(fù)制代碼

待補(bǔ)充

待補(bǔ)充

參考:juejin.im/post/5a9923…

瀏覽器在接收到 htmlcss 后,渲染的步驟是:html 經(jīng)過(guò)渲染生成 DOM 樹, css 經(jīng)過(guò)渲染生成 css 渲染樹,兩者再經(jīng)過(guò)結(jié)合,生成 render tree,瀏覽器就可以根據(jù) render tree 進(jìn)行畫面繪制。愛(ài)掏網(wǎng) - it200.com

如果瀏覽器從服務(wù)器接收到了新的 css ,需要更新頁(yè)面時(shí),需要經(jīng)過(guò)什么操作呢?這就是回流 reflow 與重繪 repaint愛(ài)掏網(wǎng) - it200.com由于瀏覽器在重新渲染頁(yè)面時(shí)會(huì)先進(jìn)行 reflow 再進(jìn)行 repaint,因此,回流必將引起重繪,而重繪不一定會(huì)引起回流。愛(ài)掏網(wǎng) - it200.com

重繪:當(dāng)前元素的樣式(背景顏色、字體顏色等)發(fā)生改變的時(shí)候,我們只需要把改變的元素重新的渲染一下即可,重繪對(duì)瀏覽器的性能影響較小。愛(ài)掏網(wǎng) - it200.com發(fā)生重繪的情形:改變?nèi)萜鞯耐庥^風(fēng)格等,比如 background:black 等。愛(ài)掏網(wǎng) - it200.com改變外觀,不改變布局,不影響其他的 DOM愛(ài)掏網(wǎng) - it200.com ?? 回流:是指瀏覽器為了重新渲染部分或者全部的文檔而重新計(jì)算文檔中元素的位置和幾何構(gòu)造的過(guò)程。愛(ài)掏網(wǎng) - it200.com

因?yàn)榛亓骺赡軐?dǎo)致整個(gè) DOM 樹的重新構(gòu)造,所以是性能的一大殺手,一個(gè)元素的回流導(dǎo)致了其所有子元素以及 DOM 中緊隨其后的祖先元素的隨后的回流。愛(ài)掏網(wǎng) - it200.com下面貼出會(huì)觸發(fā)瀏覽器 reflow 的變化:

  • 頁(yè)面首次渲染
  • 瀏覽器窗口大小發(fā)生改變
  • 元素尺寸或位置發(fā)生改變
  • 元素內(nèi)容變化(文字?jǐn)?shù)量或圖片大小等等)
  • 元素字體大小變化
  • 添加或者刪除可見的DOM元素
  • 激活CSS偽類(例如::hover)
  • 查詢某些屬性或調(diào)用某些方法

優(yōu)化方案:

CSS

  • 避免使用table布局。愛(ài)掏網(wǎng) - it200.com
  • 盡可能在DOM樹的最末端改變class愛(ài)掏網(wǎng) - it200.com
  • 避免設(shè)置多層內(nèi)聯(lián)樣式。愛(ài)掏網(wǎng) - it200.com
  • 將動(dòng)畫效果應(yīng)用到position屬性為absolutefixed的元素上。愛(ài)掏網(wǎng) - it200.com
  • 避免使用CSS表達(dá)式(例如:calc())。愛(ài)掏網(wǎng) - it200.com

JavaScript

  • 避免頻繁操作樣式,最好一次性重寫style屬性,或者將樣式列表定義為class并一次性更改class屬性。愛(ài)掏網(wǎng) - it200.com
  • 避免頻繁操作DOM,創(chuàng)建一個(gè)documentFragment,在它上面應(yīng)用所有DOM操作,最后再把它添加到文檔中。愛(ài)掏網(wǎng) - it200.com
  • 也可以先為元素設(shè)置display: none,操作結(jié)束后再把它顯示出來(lái)。愛(ài)掏網(wǎng) - it200.com因?yàn)樵?code>display屬性為none的元素上進(jìn)行的DOM操作不會(huì)引發(fā)回流和重繪。愛(ài)掏網(wǎng) - it200.com
  • 避免頻繁讀取會(huì)引發(fā)回流/重繪的屬性,如果確實(shí)需要多次使用,就用一個(gè)變量緩存起來(lái)。愛(ài)掏網(wǎng) - it200.com
  • 對(duì)具有復(fù)雜動(dòng)畫的元素使用絕對(duì)定位,使它脫離文檔流,否則會(huì)引起父元素及后續(xù)元素頻繁回流。愛(ài)掏網(wǎng) - it200.com

一般的思路就是遞歸解決,對(duì)不同的數(shù)據(jù)類型做不同的處理:

function deepCopy (obj) {
 let result = {}
 for (let key in obj) {
 if (obj[key] instanceof Object || obj[key] instanceof Array) {
 result[key] = deepCopy(obj[key])
 } else {
 result[key] = obj[key]
 }
 }
 return result
}
復(fù)制代碼

這個(gè)只能復(fù)制內(nèi)部有數(shù)組、對(duì)象或其他基礎(chǔ)數(shù)據(jù)類型的對(duì)象,假如有一些像RegExpDate這樣的復(fù)雜對(duì)象復(fù)制的結(jié)果就是一個(gè){},無(wú)法正確進(jìn)行復(fù)制,因?yàn)闆](méi)有對(duì)這些特殊對(duì)象進(jìn)行單獨(dú)的處理。愛(ài)掏網(wǎng) - it200.com若要參考對(duì)復(fù)雜對(duì)象進(jìn)行復(fù)制,可以參考lodash中數(shù)組深復(fù)制方法_.cloneDeep()的實(shí)現(xiàn)方案,下面這篇文章對(duì)數(shù)組深復(fù)制的方法進(jìn)行了詳細(xì)的解析,有一定參考價(jià)值: jerryzou.com/posts/dive-…

另外如果要復(fù)制的對(duì)象數(shù)據(jù)結(jié)構(gòu)較為簡(jiǎn)單,沒(méi)有復(fù)雜對(duì)象的數(shù)據(jù),那么可以用最簡(jiǎn)便的方法:

let cloneResult = JSON.parse(JSON.stringify(targetObj))
復(fù)制代碼

此前轉(zhuǎn)載了一篇文章,對(duì)JavaScript運(yùn)算精度丟失的原因及解決方案都有比較詳細(xì)的說(shuō)明: blog.csdn.net/qq_35271556…

瀏覽器相關(guān)

加載過(guò)程:

  • 瀏覽器根據(jù) DNS 服務(wù)器解析得到域名的 IP 地址
  • 向這個(gè) IP 的機(jī)器發(fā)送 HTTP 請(qǐng)求
  • 服務(wù)器收到、處理并返回 HTTP 請(qǐng)求
  • 瀏覽器得到返回內(nèi)容

渲染過(guò)程:

  • 根據(jù) HTML 結(jié)構(gòu)生成 DOM 樹
  • 根據(jù) CSS 生成 CSSOM
  • 將 DOM 和 CSSOM 整合形成 RenderTree
  • 根據(jù) RenderTree 開始渲染和展示
  • 遇到 復(fù)制代碼
    • $parent 一樣,在父組件中可以通過(guò)訪問(wèn) this.$children 來(lái)訪問(wèn)組件的所有子組件實(shí)例。愛(ài)掏網(wǎng) - it200.com

    非父子組件之間的數(shù)據(jù)傳遞

    • 對(duì)于非父子組件間,且具有復(fù)雜組件層級(jí)關(guān)系的情況,可以通過(guò) Vuex 進(jìn)行組件間數(shù)據(jù)傳遞: vuex.vuejs.org/zh/

    • Vue 1.0 中常用的 event bus 方式進(jìn)行的全局?jǐn)?shù)據(jù)傳遞,在 Vue 2.0 中已經(jīng)被移除,官方文檔中有說(shuō)明:$dispatch$broadcast 已經(jīng)被棄用。愛(ài)掏網(wǎng) - it200.com請(qǐng)使用更多簡(jiǎn)明清晰的組件間通信和更好的狀態(tài)管理方案,如:Vuex愛(ài)掏網(wǎng) - it200.com

    blog.seosiwei.com/detail/35 blog.seosiwei.com/detail/36 blog.seosiwei.com/detail/37

    router.vuejs.org/zh-cn/advan…


    作者:不肥的肥羊
    鏈接:https://juejin.im/post/5b0562306fb9a07aaf3596c1
    來(lái)源:掘金
    著作權(quán)歸作者所有。愛(ài)掏網(wǎng) - it200.com商業(yè)轉(zhuǎn)載請(qǐng)聯(lián)系作者獲得授權(quán),非商業(yè)轉(zhuǎn)載請(qǐng)注明出處。愛(ài)掏網(wǎng) - it200.com
聲明:所有內(nèi)容來(lái)自互聯(lián)網(wǎng)搜索結(jié)果,不保證100%準(zhǔn)確性,僅供參考。如若本站內(nèi)容侵犯了原著者的合法權(quán)益,可聯(lián)系我們進(jìn)行處理。
發(fā)表評(píng)論
更多 網(wǎng)友評(píng)論0 條評(píng)論)
暫無(wú)評(píng)論

返回頂部

主站蜘蛛池模板: 爱情岛永久地址www成人| 亚洲aⅴ无码专区在线观看q| 一级毛片aaaaaa免费看| 97se亚洲国产综合自在线| 韩国高清色www在线播放| 极品丝袜乱系列全集阅读| 国产精品一区二区久久不卡| 亚洲欧美日韩在线观看| 中文字幕精品一区二区2021年| 青娱乐在线视频观看| 欧美伊人久久大香线蕉在观| 国产精品人成在线观看| 亚洲国产av高清无码| 2022国产成人福利精品视频| 污污网站免费观看| 成人中文字幕在线| 国产女人水真多18毛片18精品| 久久精品国产99久久久| 边摸边吃奶边做爽免费视频99| 欧美中文在线观看| 国产成人教育视频在线观看| 久久精品94精品久久精品| 蜜桃成熟之蜜桃仙子| 成年人视频在线观看免费| 国产思思99re99在线观看 | 中文字幕热久久久久久久| 美女私密无遮挡网站视频| 妇女被猛烈进入在线播放| 国产交换配偶在线视频 | √天堂资源地址在线官网 | 放荡的女老板bd中文在线观看| 国产a级黄色片| 一级一看免费完整版毛片| 男人j桶女人j免费视频| 快点cao我要被cao烂了| 亚洲香蕉免费有线视频| 一区二区三区影院| 污污网站免费入口链接| 国产无遮挡AAA片爽爽| 中文字幕免费在线视频| 男人j进女人p免费视频不要下载的 |