更多课程 选择中心

Web培训
达内IT学院

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年前端面试题汇总之算法和应用

2020年前端面试题汇总之常见性能优化

2020年前端面试题汇总之Webpack

Web前端面试必备面试题整理

选择城市和中心
黑龙江省

吉林省

河北省

贵州省

云南省

广西省

海南省