最后

前端CSS面试题文档,JavaScript面试题文档,Vue面试题文档,大厂面试题文档

开源分享:【大厂前端面试题解析+核心总结学习笔记+真实项目实战+最新讲解视频】

前端性能

1、原则
(1)多使用内存、缓存或者其他方法。
(2)减少cpu占用,减少网络。

提升页面性能的方法有哪些?

一、加载页面和静态资源
1、静态资源压缩合并,减少http请求。
(1)减少http请求数量
(2)减少请求资源大小
2、非核心代码异步加载。
3、静态资源缓存:通过链接名称控制缓存,只有内容改变的时候,链接名称才会改变。
4、利用浏览器缓存
5、使用cdn让资源加载更快
6、预解析dns
7、使用ssr后端渲染,数据直接输出到html中(ssr:server site render)
二、页面渲染
1、css、js及放置位置
(1)尽量避免在HTML标签中写style属性
(2)css放前面,js放后面。
(3)避免使用CSS Expression
2、图片
(1)避免图片和iFrame等的空Src。空Src会重新加载当前页面,影响速度和效率
(2)懒加载(图片懒加载,下拉加载更多)

<img id="img1" src="preview.jpg" data-realsrc="abc.jpg">
<script type="text/javascript">
var img1 = document.getElementById('img1');
img1.src = img1.getAttribute('data-realsrc');
</script>

3、dom操作
(1)减少dom查询,对dom查询做缓存。

// 未缓存dom查询
var i;
for (i = 0; i < document.getElementsByTagName('p').length; i++) {\
	// todo
}
// 缓存了dom查询
var pList = document.getElementByTagName('p');
var i;
for (i = 0; i < pList.length; i++) {
 // todo
}

(2)减少dom操作,多个操作尽量合并在一起执行。

var frag = document.createDocumentFragment(); // 片段,循环插入dom,改成先插入到片段,再append到文档流

(3)用innerHTML代替DOM操作,减少DOM操作次数,优化javascript性能
4、事件
(1)尽早执行操作(如DOMContentLoaded)
(2)事件节流

var textarea = document.getElementById('text');
var timeoutId;
textarea.addEventListener('keyup', function() {
	if(timeoutId) {
		clearTimeout(timeoutId);
	}
	timeoutId = setTimeout(function() {
		// 触发change事件
	}, 100)
})

5、代码细节优化
(1)用hash-table来优化查找
(2)多个变量声明合并
(3)少用全局变量
(4)避免全局查询
(5)避免使用with(with会创建自己的作用域,会增加作用域链长度)
(6)用setTimeout来避免页面失去响应
三、移动端性能优化
1、css
(1)不滥用Float。Float在渲染时计算量比较大,尽量减少使用
(2)不滥用Web字体。Web字体需要下载,解析,重绘当前页面,尽量减少使用。
(3)避免使用css3渐变阴影效果。
2、css动画
(1)尽量使用css3动画,开启硬件加速。
可以用transform: translateZ(0)来开启硬件加速。
CSS中的属性(CSS3 transitions、CSS3 3D transforms、Opacity、Canvas、WebGL、Video)会触发GPU渲染,请合理使用。过渡使用会引发手机过耗电增加
3、合理使用requestAnimationFrame动画代替setTimeout
4、适当使用touch事件代替click事件。

什么是防抖和节流?有什么区别?如何实现??

防抖
触发高频事件后n秒内函数只会执行一次,如果n秒内高频事件再次被触发,则重新计算时间
思路:
每次触发事件时都取消之前的延时调用方法

function debounce(fn) {
      let timeout = null; // 创建一个标记用来存放定时器的返回值
      return function () {
        clearTimeout(timeout); // 每当用户输入的时候把前一个 setTimeout clear 掉
        timeout = setTimeout(() => { // 然后又创建一个新的 setTimeout, 这样就能保证输入字符后的 interval 间隔内如果还有字符输入的话,就不会执行 fn 函数
          fn.apply(this, arguments);
        }, 500);
      };
    }
    function sayHi() {
      console.log('防抖成功');
    }

    var inp = document.getElementById('inp');
    inp.addEventListener('input', debounce(sayHi)); // 防抖

节流
高频事件触发,但在n秒内只会执行一次,所以节流会稀释函数的执行频率
思路:
每次触发事件时都判断当前是否有等待执行的延时函数

function throttle(fn) {
      let canRun = true; // 通过闭包保存一个标记
      return function () {
        if (!canRun) return; // 在函数开头判断标记是否为true,不为true则return
        canRun = false; // 立即设置为false
        setTimeout(() => { // 将外部传入的函数的执行放在setTimeout中
          fn.apply(this, arguments);
          // 最后在setTimeout执行完毕后再把标记设置为true(关键)表示可以执行下一次循环了。当定时器没有执行的时候标记永远是false,在开头被return掉
          canRun = true;
        }, 500);
      };
    }
    function sayHi(e) {
      console.log(e.target.innerWidth, e.target.innerHeight);
    }
    window.addEventListener('resize', throttle(sayHi));

  • 非核心代码异步加载

异步加载的方式?

1、动态脚本加载
script标签,加入到body中
2、defer
加载js的时候,script标签加defer和async
3、async

异步加载的区别?

1、defer是在html解析完之后才会执行,如果是多个,按照加载的顺序依次进行。
2、async是在加载完之后立即执行,如果是多个,执行顺序和加载顺序无关。

  • 预解析dns

预解析dns的方式?

1、

<link rel="dns-prefetch" href="//host_name_to_prefetch.com">

2、强制打开a标签的dns预解析

<meta http-equiv="x-dns-prefetch-control" content="on">

页面中所有a标签,默认打开了dns预解析,如果链接是https开头的,默认关闭dns预解析


多端

小程序和 H5 有什么区别?

1、渲染方式与 H5 不同,小程序一般是通过 Native 原生渲染的,但是小程序同时也支持 web 渲染,如果使用 web 渲染的方式,我们需要初始化一个WebView 组件,然后在 WebView 中加载 H5 页面;
所以当我们开发一个小程序时,通常会使用 hybrid 的方式,即会根据具体情况选择部分功能用小程序原生的代码来开发,部分功能通过 WebView 加载 H5 页面来实现。Native 与 Web 渲染混合使用,以实现项目的最优解;
这里值得注意的是,小程序下,native 方式通常情况下性能要优于 web 方式。
2、小程序特有的双线程设计。 H5 下我们所有资源通常都会打到一个 bundle.js 文件里(不考虑分包加载),而小程序编译后的结果会有两个bundle,index.js封装的是小程序项目的 view 层,以及 index.worker.js 封装的是项目的业务逻辑,在运行时,会有两条线程来分别处理这两个bundle,一个是主渲染线程,它负责加载并渲染 index.js 里的内容,另外一个是 Service Worker线 程,它负责执行 index.worker.js 里封装的业务逻辑,这里面会有很多对底层api调用。


算法相关

通常情况下,搞金融的都会考算法。
一、排序
在这里插入图片描述
快速排序:https://segmentfault.com/a/1190000009426421
选择排序:https://segmentfault.com/a/1190000009366805
希尔排序:https://segmentfault.com/a/1190000009461832
二、堆栈、队列、链表
堆栈:https://juejin.im/entry/58759e79128fe1006b48cdfd
队列:https://juejin.im/entry/58759e79128fe1006b48cdfd
链表:https://juejin.im/entry/58759e79128fe1006b48cdfd
(1)js数组本身就具备堆栈和队列特性。
(2)堆栈:先进后出。
三、递归
递归:https://segmentfault.com/a/1190000009857470
(1)60%的算法题都用到递归。
四、波兰式和逆波兰式
理论:http://www.cnblogs.com/chenying99/p/3675876.html
源码:https://github.com/Tairraos/rpn.js/blob/master/rpn.js

手写一个冒泡排序?

1、比较两个相邻的元素,如果后一个比前一个大,则交换位置。
2、 第一轮的时候最后一个元素应该是最大的一个。
3、按照第一步的方法进行两个相邻的元素的比较,由于最后一个元素已经是最大的了,所以最后一个元素不用比较。

 function bubbleSort(arr) {
    let len = arr.length;
    for (let i = 0; i < len; i++) {
       for (let j = 0; j < len - i - 1; j++) { // j=0时,得到最大的元素,放在了最后面
         if (arr[j] > arr[j+1]) {
           [arr[j], arr[j+1]] = [arr[j+1], arr[j]];
         }
       }
    }
    return arr;
  }
  let arr = [3,5,1,2,7,8,4,5,3,4];
  let sortedArr = bubbleSort(arr);
  console.log(sortedArr);

快速排序的思想?

1、在数据集之中,找一个基准点,将数据分成两个部分,一部分比另外一部分所有的数据都要小,
2、建立两个数组,分别存储左边和右边的数组
3、利用递归进行下次比较

手写一个快速排序?
 function quickSort(arr) {
    if (arr.length <= 1) { // 如果数组长度小于等于1无需判断直接返回即可
      return arr;
    }
    var pivotIndex = Math.floor(arr.length / 2); // 取基准点
    var pivot = arr.splice(pivotIndex, 1)[0]; // 取基准点的值,splice(index,1)函数可以返回数组中被删除的那个数
    var left = []; // 存放比基准点小的数组
    var right = []; // 存放比基准点大的数组
    for (var i = 0; i < arr.length; i++) {  // 遍历数组,进行判断分配
      if (arr[i] < pivot) {
        left.push(arr[i]); // 比基准点小的放在左边数组
      } else {
        right.push(arr[i]); // 比基准点大的放在右边数组
      }
    }
    //递归执行以上操作,对左右两个数组进行操作,直到数组长度为<=1;
    return quickSort(left).concat([pivot], quickSort(right));
  };
  var arr = [1, 2, 3, 55, 7, 99, 8, 100, 1021];
  var sortedArr = quickSort(arr);
  console.log(sortedArr);


设计模式

用过哪些设计模式?

1、工厂模式:

主要好处就是可以消除对象间的耦合,通过使用工程方法而不是new关键字。将所有实例化的代码集中在一个位置防止代码重复。
工厂模式解决了重复实例化的问题 ,但还有一个问题,那就是识别问题,因为根本无法搞清楚他们到底是哪个对象的实例。

function createObject(name,age,profession){//集中实例化的函数var obj = newObject();
    obj.name =name;
    obj.age = age;
    obj.profession= profession;
    obj.move =function () {
        returnthis.name + ' at ' + this.age + ' engaged in ' + this.profession;
    };
    return obj;
}
var test1 = createObject('trigkit4',22,'programmer');//第一个实例
var test2 =createObject('mike',25,'engineer');//第二个实例

2、构造函数模式
使用构造函数的方法 ,即解决了重复实例化的问题 ,又解决了对象识别的问题,该模式与工厂模式的不同之处在于:
①构造函数方法没有显示的创建对象 (new Object());
②直接将属性和方法赋值给 this 对象;
③没有 renturn 语句。

JS的四种设计模式?

工厂模式
简单的工厂模式可以理解为解决多个相似的问题;

function CreatePerson(name,age,sex) {
    var obj = new Object();
    obj.name = name;
    obj.age = age;
    obj.sex = sex;
    obj.sayName = function(){
        return this.name;
    }
    return obj;
}
var p1 = new CreatePerson("longen",'28','男');
var p2 = new CreatePerson("tugenhua",'27','女');
console.log(p1.name); // longen
console.log(p1.age);  // 28
console.log(p1.sex);  // 男
console.log(p1.sayName()); // longen

console.log(p2.name);  // tugenhua
console.log(p2.age);   // 27
console.log(p2.sex);   // 女
console.log(p2.sayName()); // tugenhua  

单例模式
只能被实例化(构造函数给实例添加属性与方法)一次

// 单体模式
var Singleton = function(name){
    this.name = name;
};
Singleton.prototype.getName = function(){
    return this.name;
}
// 获取实例对象
var getInstance = (function() {
    var instance = null;
    return function(name) {
        if(!instance) {//相当于一个一次性阀门,只能实例化一次
            instance = new Singleton(name);
        }
        return instance;
    }
})();
// 测试单体模式的实例,所以a===b
var a = getInstance("aa");
var b = getInstance("bb");  

沙箱模式
将一些函数放到自执行函数里面,但要用闭包暴露接口,用变量接收暴露的接口,再调用里面的值,否则无法使用里面的值

let sandboxModel=(function(){
    function sayName(){};
    function sayAge(){};
    return{
        sayName:sayName,
        sayAge:sayAge
    }
})()

发布者订阅模式
就例如如我们关注了某一个公众号,然后他对应的有新的消息就会给你推送,

//发布者与订阅模式
    var shoeObj = {}; // 定义发布者
    shoeObj.list = []; // 缓存列表 存放订阅者回调函数

    // 增加订阅者
    shoeObj.listen = function(fn) {
        shoeObj.list.push(fn); // 订阅消息添加到缓存列表
    }

    // 发布消息
    shoeObj.trigger = function() {
            for (var i = 0, fn; fn = this.list[i++];) {
                fn.apply(this, arguments);//第一个参数只是改变fn的this,
            }
        }
     // 小红订阅如下消息
    shoeObj.listen(function(color, size) {
        console.log("颜色是:" + color);
        console.log("尺码是:" + size);
    });

    // 小花订阅如下消息
    shoeObj.listen(function(color, size) {
        console.log("再次打印颜色是:" + color);
        console.log("再次打印尺码是:" + size);
    });
    shoeObj.trigger("红色", 40);
    shoeObj.trigger("黑色", 42);  

代码实现逻辑是用数组存贮订阅者, 发布者回调函数里面通知的方式是遍历订阅者数组,并将发布者内容传入订阅者数组

  • MVVM

对mvvm的理解?

1、MVVM 是 Model-View-ViewModel 的缩写。
2、Model代表数据模型,也可以在Model中定义数据修改和操作的业务逻辑。
3、View 代表UI 组件,它负责将数据模型转化成UI 展现出来。
4、ViewModel 监听模型数据的改变和控制视图行为、处理用户交互,简单理解就是一个同步View 和 Model的对象,连接Model和View。
5、在MVVM架构下,View 和 Model 之间并没有直接的联系,而是通过ViewModel进行交互,Model 和 ViewModel 之间的交互是双向的, 因此View 数据的变化会同步到Model中,而Model 数据的变化也会立即反应到View 上。
ViewModel 通过双向数据绑定把 View 层和 Model 层连接了起来,而View 和 Model 之间的同步工作完全是自动的,无需人为干涉,因此开发者只需关注业务逻辑,不需要手动操作DOM, 不需要关注数据状态的同步问题,复杂的数据状态维护完全由 MVVM 来统一管理。

mvvm框架实现的三要素/ vue的三要素?

1、响应式:vue如何监听到data的每个属性变化?
(1)修改data属性后,vue立刻监听到。Object.defineProperty

var __name = 'may';
Object.defineProperty(obj, 'name',{
	get: function() {
		return __name;
	},
	set: function(newVal) {
		__name = newVal; // 修改__name = 'april',obj.name就会变成april
	}
})

(2)data属性代理到vm上
2、模板引擎:vue的模板如何被解析,指令如何处理?
(1)模板是什么
①本质:字符串
②有逻辑,如v-if, v-for等
③与html格式很像,但有很大区别
④模板最终必须转换成Js代码(js函数-render函数),因为
有逻辑(v-if, v-for),必须用js才能实现(图灵完美语言)
转换为html渲染页面,必须用js才能实现
(2)render函数
(3)render函数与vdom
3、渲染:vue的模板如何被渲染成Html?以及渲染过程?


正则表达式

写一个function,清除字符串前后的空格。(兼容所有浏览器)?
function trim(str) {
	if (str && typeof str === 'string') {
		return str.replace(/(^\s*)|(\s*)$/g, '');
	}
}


hybrid

15、hybrid业务开发经验,对离线包机制熟悉,多各种优化方案也了解得比较清楚。

7、离线包加载和更新机制,
22、servive worker, web worker


全栈

8、图片加载的一个细节,能够从全栈角度给出一些高并发情况下的系统扩展思路
27、跨域access-control-allow-origin多域名白名单处理
cdn部署
前端框架选型
人员协调项目延期
整个部门没有用到mock平台,前后端分离
自己写了服务在服务端用webpack+multi方式融合不同的业务模块打包
Mbox的数据管理方案(mbox的数据状态流转机制)
数据库,数据索引,事务,数据库锁的问题

5、前端核心监控数据来源(performance api + 业务定义为主)

31、逻辑外链如何保持多个数据同步

项目

16、资讯类的项目,有哪些技术特点(本想了解list相关的回答)
详情里面做了哪些
详情页对性能要求高,有哪些优化?配置缓存来优化。
缓存如何配置,
哪些缓存头来控制的缓存
类似静态化的性能优化,采用ssr比较适合详情页的技术
1、哪些工作是偏技术的,需要技术来解决的

svn、git

get fetch、git pull的区别

1、git fetch是将远程主机的最新内容拉到本地,用户在检查了以后决定是否合并到工作本机分支中。
2、git pull 则是将远程主机的最新内容拉下来后直接合并,即:git pull = git fetch + git merge,这样可能会产生冲突,需要手动解决。

前端面试题汇总

JavaScript

开源分享:【大厂前端面试题解析+核心总结学习笔记+真实项目实战+最新讲解视频】

性能

linux

前端资料汇总

get fetch、git pull的区别

1、git fetch是将远程主机的最新内容拉到本地,用户在检查了以后决定是否合并到工作本机分支中。
2、git pull 则是将远程主机的最新内容拉下来后直接合并,即:git pull = git fetch + git merge,这样可能会产生冲突,需要手动解决。

前端面试题汇总

JavaScript

开源分享:【大厂前端面试题解析+核心总结学习笔记+真实项目实战+最新讲解视频】

性能

linux

前端资料汇总

Logo

前往低代码交流专区

更多推荐