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);
}

Web大前端面试题-Day4的更多相关文章

  1. Web大前端面试题-Day12

    1.前端需要注意哪些SEO? 合理的title.description.keywords: 搜索对着三项的权重逐个减小, title值强调重点即可, 重要关键词出现不要超过2次, 而且要靠前, 不同页 ...

  2. Web大前端面试题-Day7

    1. 你能描述一下渐进增强和优雅降级之间的不同吗? 定义: 优雅降级(graceful degradation): 一开始就构建站点的完整功能, 然后针对浏览器测试和修复 渐进增强(progressi ...

  3. Web大前端面试题-Day6

    1.请说明ECMAScript, JavaScript, Jscript之间的关系? ECMAScript提供脚本语言必须遵守的规则. 细节和准则,是脚本语言的规范. 比如:ES5,ES6就是具体的一 ...

  4. Web大前端面试题-Day11

    86.如何获得高效的数据库逻辑结构? 从关系数据库的表中 删除冗余信息的过程 称为数据规范化, 是得到高效的关系型数据库表的逻辑结构 最好和最容易的方法. 规范化数据时应执行以下操作: 1.将数据库的 ...

  5. Web大前端面试题-Day10

    1. px和em的区别? px和em都是长度单位; 区别是: px的值是固定的,指定是多少就是多少, 计算比较容易. em得值不是固定的,并且em会继承父级元素的字体大小. 浏览器的默认字体高都是16 ...

  6. Web大前端面试题-Day8

    1. 说说你对作用域链的理解? 作用域链的作用是保证执行环境里 有权访问的变量和函数是有序的, 作用域链的变量只能向上访问, 变量访问到window对象即被终止, 作用域链向下访问变量是不被允许的; ...

  7. Web大前端面试题-Day1

    1. var的变量提升的底层原理是什么? JS引擎的工作方式是:1) 先解析代码,获取所有被声明的变量:2)然后在运行.也就是说分为预处理和执行两个阶段. 变量提升:所有变量的声明语句都会被提升到代码 ...

  8. Web大前端面试题-Day9

    1. 请用至少3中方式实现数组去重? 方法一: indexOfvar arr1=[1,2,3,4,5,4,3,2,1];  function repeat1(arr){    for(var i=0, ...

  9. Web大前端面试题-Day5

    1.写一个深度克隆方法(es5)? /** *  深拷贝 * @param {object}fromObj 拷贝的对象 * @param {object}toObj  目标对象 */ function ...

随机推荐

  1. 「Vue」watch基本用法

    应用于监视路由地址改变,如有新地址(即路由地址改变)即执行自定义方法 methods: { itemShow() { this.$axios.get('item/item/'+this.id+'?to ...

  2. MVC、MVP和MVVM浅谈

    MVC是最经典的开发模式之一,最早是后台那边来的,后台前端的复杂度也上来了,MVC的开发模式也带进前端了. MVC: MVC有两个很明显的问题: 1.m层和v层直接打交道,导致这两层耦合度高 2.因为 ...

  3. Hadoop生态圈-zookeeper本地搭建以及常用命令介绍

    Hadoop生态圈-zookeeper本地搭建以及常用命令介绍 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.下载zookeeper软件 下载地址:https://www.ap ...

  4. 设计模式之Mixin模式

    介绍 mixin模式就是一些提供能够被一个或者一组子类简单继承功能的类,意在重用其功能.在面向对象的语言中,我们会通过接口继承的方式来实现功能的复用.但是在javascript中,我们没办法通过接口继 ...

  5. POJ - 2513 Colored Sticks(欧拉通路+并查集+字典树)

    https://vjudge.net/problem/POJ-2513 题解转载自:優YoU  http://user.qzone.qq.com/289065406/blog/1304742541 题 ...

  6. poj 2947 Widget Factory (高斯消元解同余方程组+判断无解、多解)

    http://poj.org/problem?id=2947 血泪史: CE:poj的string类型要加string库,swap不能直接交换数组 WA: x[m-1]也有可能<3啊O(≧口≦) ...

  7. POJ 3710 无向图简单环树上删边

    结论题,这题关键在于如何转换环,可以用tarjan求出连通分量后再进行标记,也可以DFS直接找到环后把点的SG值变掉就行了 /** @Date : 2017-10-23 19:47:47 * @Fil ...

  8. 概率dp(A - Scout YYF I POJ - 3744 )

    题目链接:https://cn.vjudge.net/contest/276241#problem/A 题目大意:首先输入n和p,n代表地雷的个数,p代表走一步的概率,1-p代表走两步的概率,然后问你 ...

  9. Linux DRM KMS 驱动简介【转】

    转自:https://blog.csdn.net/yangkuanqaz85988/article/details/48689521 Whoops,上次写完<Linux DRM Graphic ...

  10. CRT软件光标不闪烁

    点击 选项->会话选项 然后在取消即可,就有了闪烁的光标,应该是个bug 也可以把后面的浏览器之类的东西缩小一下,也会恢复