更多課程 選擇中心

Web培訓
美國上市教育機構

400-111-8989

Web培訓

2020年Web前端面試題匯總(六)

  • 發布:Web前端培訓
  • 來源:web前端面試
  • 時間:2020-06-18 14:49

今天小編要跟大家分享的文章是關于2020年Web前端面試題匯總。由于內容較多小編分開為大家介紹,今天來和小編一起看一看第六部分的內容,希望這些面試題能夠對正準備找Web前端相關工作的小伙伴們有所幫助。下面來和小編一起看一看吧!

2020年Web前端面試題匯總(六)

1. 如何實現瀑布流?

瀑布流布局的原理:

1) 瀑布流布局要求要進行布置的元素等寬,

然后計算元素的寬度,

與瀏覽器寬度之比,得到需要布置的列數;

2) 創建一個數組,長度為列數,

里面的值為已布置元素的總高度(最開始為0);

3) 然后將未布置的元素依次布置到高度最小的那一列,

就得到了瀑布流布局;

4) 滾動加載, scroll事件得到scrollTop,

與最后盒子的offsetTop對比,

符合條件就不斷滾動加載。

瀑布流布局核心代碼:

/**

* 實現瀑布流的布局

* @param {string}parentBox

* @param {string}childBox

*/

function waterFull(parentBox, childBox) {

// 1. 求出父盒子的寬度

// 1.1 獲取所有的子盒子

var allBox = $(parentBox).

getElementsByClassName(childBox);

// 1.2 求出子盒子的寬度

var boxWidth = allBox[0].offsetWidth;

// 1.3 獲取窗口的寬度

var clientW = document.

documentElement.clientWidth;

// 1.4 求出總列數

var cols = Math.floor(clientW / boxWidth);

// 1.5 父盒子居中

$(parentBox).style.width = cols * boxWidth + 'px';

// 2. 子盒子定位

$(parentBox).style.margin = '0 auto';

// 2.1 定義變量

var heightArr = [], boxHeight = 0,

minBoxHeight = 0, minBoxIndex = 0;

// 2.2 遍歷所有的子盒子

for (var i = 0; i < allBox.length; i++) {

// 2.2.1 求出每一個子盒子的高度

boxHeight = allBox[i].offsetHeight;

// 2.2.2 取出第一行盒子的高度放入高度數組中

if (i < cols) { // 第一行

heightArr.push(boxHeight);

} else { // 剩余行的盒子

// 2.2.3 取出數組中最矮的高度

minBoxHeight = _.min(heightArr);

// 2.2.4 求出最矮高度對應的索引

minBoxIndex = getMinBoxIndex(heightArr, minBoxHeight);

// 2.2.5 盒子定位

allBox[i].style.position = 'absolute';

// 2.2.6 更新最矮的高度

allBox[i].style.left = minBoxIndex * boxWidth + 'px';

allBox[i].style.top = minBoxHeight + 'px';

heightArr[minBoxIndex] += boxHeight;

}

}

}

/**

* 根據內容取出在數組中對應的索引

* @param {object}arr

* @param {number}val

* @returns {boolean}

*/

function getMinBoxIndex(arr, val) {

for (var i = 0; i < arr.length; i++) {

if (arr[i] === val) return i;

}

}

/**

* 判斷是否具備加載子盒子的條件

* @returns {boolean}

*/

function checkWillLoadImage() {

// 1. 獲取最后一個盒子

var allBox = $('main').getElementsByClassName('box');

var lastBox = allBox[allBox.length - 1];

// 2. 求出高度

var lastBoxDis = lastBox.offsetHeight * 0.5 + lastBox.offsetTop;

// 3. 求出窗口的高度

var clientH = document.documentElement.clientHeight;

// 4. 求出頁面滾動產生的高度

var scrollTopH = scroll().top;

// 5. 對比

return lastBoxDis <= clientH + scrollTopH;

}

2. 原生JS都有哪些方式可以實現兩個頁面間的通信?

1) 通過url地址欄傳遞參數;

例如:點擊列表頁中的每一條數據,

我們跳轉到同一個詳細頁面,

但是根據點擊的不一樣可以看到

不同的內容,這樣的話我們就可以

在URL中傳遞不同的值來區分了;

2) 通過本地存儲 cookie、localeStorage、

sessionStroage...,例如:京東的登錄,

我們在登錄頁登錄完成后,

把用戶信息存儲到本地,

然后在其它頁面中如果需要使用的話,

我們直接從本地的存儲數據中拿

出來用即可;

3) 使用iframe在A頁面中嵌入B頁面,

這樣的話,在A中可以通過一些屬性

和方法實現和B頁面的通信;

4) 利用postMessage實現頁面間通信,

父窗口往子窗口傳遞信息,

子窗口往父窗口傳遞信息。

3. 原生JS動態向一個div中插入1000個div標簽,如何實現?

此題主要考性能!

1) 可以用JS中的createElement創建div,

每當創建一個就把它添加到div中,

但會造成引發回流的次數太多;

2) 使用字符串拼接的方式,

把1000個div都拼接完成后,

統一的添加到頁面中,

但會對div原有的元素標簽產生影響:

原來標簽綁定的事件都消失了

3) 綜合1和2可以使用文檔碎片方式來處理。

追問:如果是創建1000萬個呢?

可采用的方案: 數據分批異步加載

1) 首先把前兩屏幕的數據量

(例如:300條)先獲取到,

然后使用字符串拼接或者文檔碎片

的方式綁定到頁面中;

2) 當瀏覽器滾動到指定的區域的

時候在加載300條...以此類推。

4. 程序出現bug了,你是如何調試的?

1) 在控制臺加斷點,

F10->逐過程 F11->逐語句;

2) 在代碼重點的位置加入

console.log輸出對應的值來進行調試;

3) debugger調試;

4) 代碼分割還原調試;

5) 異常捕獲機制, 記錄運行日志;

6) 單元測試。

5. 開發中是如何進行性能優化的?

現在框架(vue, react,...)、構建工具(webpack, ...)

已經給我們解決掉大部分的性能優化問題,

面試時, 可以就你了解的框架來深入剖析,

但此題應該是考原生JS的范疇,

參考答案如下:

1) 雅虎35條性能優化黃金定律;

2) JS代碼優化:

a. 項目中的JS/CSS文件最好一個頁面只用一個,

需要把JS/CSS進行合并壓縮,

并且減少頁面中的垃圾冗余代碼。

項目的資源文件在服務器上最好

做一下GZIP壓縮。

b. 解除文件緩存;

我們修改代碼并上傳,

如果之前頁面訪問過該網站,

很有可能不能立即見效;

我們在引入CSS/JS文件的時候,

在文件名的后面加上版本號(加時間戳),

比如:

<script src='itlike.com.js?_=202001...'></script>;

當我們上傳新的文件后

把時間戳改一下就可以清除緩存了。

c. 移動端盡量少用圖片:

icon能用svg畫的不用圖片;

靜態資源圖:做布局的時候就能確定下來的圖片,

比如:

1) css sprite圖片合并

(針對于小圖片)

2) 做圖片延遲加載

(針對于大圖片 頭部的長條圖片、背景大圖...),

開始給一張默認的小的圖片

(最好維持在10kb以內)

3) base64 (存在問題: 頁面的代碼太臃腫了,以后維護不好操作);

如果項目中由于圖片太大實在解決不了,

改成base64就解決了

d. 動態數據圖:

通過ajax從后臺讀取回來的圖片 , 圖片懶加載;

e. 音視頻文件的優化:

加載頁面的時候,盡量不要加載音視頻文件,

當頁面中的其他資源加載完成后,

再開始加載音視頻文件;

目前移動端經常給音視頻做的優化是:

走直播流文件(音頻后綴名是m3u8格式);

f. 減少頁面資源請求的次數:

如果當前只是一個宣傳頁,

或者是一個簡單的頁面,

使用的css和js可以采用內嵌式開發;

g. ajax數據請求分批請求,

例如:一次要請求10000條數據的話,

我們每一次只請求100條,第一屏幕肯定能看全了,

當頁面滾動到對應的其它屏幕的時候,

在加載下一個100條...

h. 做數據的二次緩存,

能用CSS3做動畫的絕對不用JS,

能使用transform盡量使用,

能用animation的進行不用transition...

盡量減少同步操作,多用異步操作;

能使用原生JS自己編寫的,

絕對不用插件或者框架;

6. 如何實現電商網站中的樓層效果?

1) 封裝緩動動畫函數;

2) 點擊切換, 滾動切換, 聯動處理;

核心代碼如下:

// 3. 監聽GPS上的li的點擊

for (var j = 0; j < olLis.length; j++) {

(function (index) {

var olLi = olLis[index];

olLi.onmousedown = function () {

isClick = true;

// 3.1 排他

for (var m = 0; m < olLis.length; m++) {

olLis[m].className = ''

}

addClass(this, 'current');

// 3.2 讓樓層滾動起來

buffer( document.documentElement,

{'scrollTop': index * client().height},

function () {

isClick = false;

})

}

})(j)

}

// 4. 監聽文檔的滾動

window.onscroll = function (ev1) {

// 4.1 沒有點擊產生的滾動

if (!isClick) {

// 4.2 獲取頁面產出的頭部滾動的高度

var roll = Math.ceil(scroll().top);

console.log(roll);

// 4.3 遍歷

for (var i = 0; i < olLis.length; i++) {

// 4.4 判斷

if (roll >= ulLis[i].offsetTop) {

for (var m = 0; m < olLis.length; m++) {

olLis[m].className = '' }

addClass(olLis[i], 'current');

}

}

}

}

緩動動畫函數:

/**

* 緩動動畫(撩課學院)

* @param {object}obj

* @param {object}json

* @param {function}fn

*/

function buffer(obj, json, fn) {

// 1.1 清除定時器 clearInterval(obj.timer);

// 1.2 設置定時器

var begin = 0, target = 0, speed = 0;

obj.timer = setInterval(function () {

// 1.3.0 旗幟

var flag = true;

for (var k in json) {

// 1.3 獲取初始值

if ("opacity" === k) {

// 透明度

begin = parseInt(parseFloat(getCSSAttrValue(obj, k)) * 100);

target = parseInt(parseFloat(json[k]) * 100);

} else if ("scrollTop" === k) {

begin = Math.ceil(obj.scrollTop);

target = parseInt(json[k]);

} else {

// 其他情況

begin = parseInt(getCSSAttrValue(obj, k)) || 0;

target = parseInt(json[k]);

}

// 1.4 求出步長

speed = (target - begin) * 0.2;

// 1.5 判斷是否向上取整

speed = (target > begin)? Math.ceil(speed): Math.floor(speed);

// 1.6 動起來

if ("opacity" === k) {

// 透明度// w3c的瀏覽器

obj.style.opacity = (begin + speed) / 100;

// ie 瀏覽器

obj.style.filter = 'alpha(opacity:' + (begin + speed) + ')';

} else if ("scrollTop" === k) {

obj.scrollTop = begin + speed;

} else if ("zIndex" === k) {

obj.style[k] = json[k];

} else {

obj.style[k] = begin + speed + "px";

}

// 1.5 判斷

if (begin !== target) {

flag = false;

}

}

// 1.3 清除定時器

if (flag) {

clearInterval(obj.timer);

// 判斷有沒有回調函數

if (fn) {

fn();

}

}

}, 20);

}

7.寫一個深度克隆方法(es5)?

/**

* 深拷貝

* @param {object}fromObj 拷貝的對象

* @param {object}toObj 目標對象

*/

function deepCopyObj2NewObj(fromObj, toObj) {

for(var key in fromObj){

// 1. 取出鍵值對

var fromValue = fromObj[key];

// 2. 檢查當前的屬性值是什么類型

if(!isObj(fromValue)){

// 如果是值類型,那么就直接拷貝賦值

toObj[key] = fromValue;

}else {

// 如果是引用類型,

// 那么就再調用一次這個方法,

// 去內部拷貝這個對象的所有屬性

var tempObj = new fromValue.constructor;

console.log(fromValue.constructor);

deepCopyObj2NewObj(fromValue, tempObj);

toObj[key] = tempObj;

}

}

}

/**

* 輔助函數, 判斷是否是對象

* @param {object}obj

* @returns {boolean}

*/

function isObj(obj) {

return obj instanceof Object;

}

8. es6中let,const,var的區別是什么?

var :聲明全局變量;

let :聲明塊級變量,即局部變量, 定義后可以修改;

const :用于聲明常量,就是定義后

不能再修改值或者引用值的常量,

也具有塊級作用域

9. 對數組[1,2,3,8,2,8]進行去重,es5或者es6方法?

es四種方式:

Array.prototype.unique1 = function() {

// 1. 定義數組

var temp = [];

// 2. 遍歷當前數組

for(var i = 0; i < this.length; i++) {

// 3.如果當前數組的第i已經保存進了臨時數組,

// 那么跳過,否則把當前項push到臨時數組里面

if (-1 === temp.indexOf(this[i])) {

temp.push(this[i]);

}

}

return temp;

};

Array.prototype.unique2 = function() {

//1. hash為hash表,r為臨時數組

var hash = {}, temp=[];

// 2.遍歷當前數組

for(var i = 0; i < this.length; i++)

{

// 3. 如果hash表中沒有當前項

if (!hash[this[i]])

{

// 4.存入hash表

hash[this[i]] = true;

// 5.把當前數組的當前項

// push到臨時數組里面

temp.push(this[i]);

}

}

return temp;

};

Array.prototype.unique3 = function() {

var n = [this[0]];

for(var i = 1; i < this.length; i++){

if (this.indexOf(this[i]) === i) {

n.push(this[i]);

}

}

return n;

};

Array.prototype.unique4 = function() {

this.sort();

var re=[this[0]];

for(var i = 1; i < this.length; i++)

{

if( this[i] !== re[re.length-1])

{

re.push(this[i]);

}

}

return re;

};

es6:Array.prototype.unique=Array.prototype.unique || function () {

return [...new Set(this)];

};

10. 說說對es6中=>的理解?

箭頭函數相當于匿名函數,

并且簡化了函數定義,

箭頭左邊是參數,

右邊是返回值。

箭頭函數看上去

是匿名函數的一種簡寫,

但實際上,箭頭函數和

匿名函數有個明顯的區別:

箭頭函數內部的this是詞法作用域,

由上下文確定。

11. 點擊一個按鈕,發出ajax請求,如何防止用戶在此請求方式返回之前再次點擊?

// 點擊提交按鈕的時候,

// 把這個提交這個處理函數給解綁掉,

// 請求完成的時候在綁定回來

function clickHandler(){

$(this).unbind('click', clickHandler);

$.ajax({

url : 'url',

dataType : 'json',

type : 'post',

success : function (data) {

if (data.success) {

//提交成功做跳轉處理

} else {

//處理失敗,重新綁定點擊事件

$(self).click(clickHandler);

}

}

}

);}

$('#itlike').click(clickHandler);

// 可以點擊后讓按鈕不可用,

// 如果提交失敗可以再次設置為可用

// 1.讓按鈕不可用

$("#itlike").attr("disabled","disabled");

$.ajax({

url : 'url',

dataType : 'json',

type : 'post',

success : function (data) {

if (data.success) {

// 提交成功做跳轉處理

} else {

// 處理失敗,重新綁定點擊事件

// 讓按鈕可用

$("#itlike").removeAttr("disabled");

}

}

});

以上就是小編今天為大家分享的關于2020年Web前端面試題匯總(六)的文章,希望本篇文章能夠對想要參加Web前端面試的小伙伴們有所幫助,想要了解更多Web前端相關知識記得關注達內Web培訓官網。最后祝愿小伙伴們面試成功,成為一名優秀的Web前端工程師

【免責聲明:本文圖片及文字信息均由小編轉載自網絡,旨在分享提供閱讀,版權歸原作者所有,如有侵權請聯系我們進行刪除。】

預約申請免費試聽課

填寫下面表單即可預約申請免費試聽!怕錢不夠?可就業掙錢后再付學費! 怕學不會?助教全程陪讀,隨時解惑!擔心就業?一地學習,可全國推薦就業!

上一篇:2020年Web前端面試題匯總(五)
下一篇:Web前端基礎面試題之性能優化

2020年Web前端面試題匯總(六)

2020年Web前端面試題匯總(五)

2020年Web前端面試題匯總(四)

2020年Web前端面試題匯總(三)

選擇城市和中心
黑龍江省

吉林省

河北省

貴州省

云南省

廣西省

海南省

欧美在线v中文字幕