2020前端面试题目

210 阅读17分钟

1. cookie,localStorage,sessionStorage

  • cookie 数据始终在同源的http请求中携带,即cookie在浏览器和服务器之间传递,而sessionStoage和localStoage不会自动把数据发给服务器,仅在本地存储。
  • 存储大小的限制,cookie存储大小4K,同时因为cookie每次请求都会携带,所以cookie只适合保存很小的数据,而sessionStoage和localStoage大小限制在5M或者更大
  • 数据有效期不同,sessionStoage在浏览器窗口未关闭前有有效,localStoage始终有效,cookie只在设置有效期内有效
  • 作用域不同,sessionStoage 只在当前页面共享,localStoage和cookie在所有同源窗口中都是共享的

2. 输入URL发生什么

  • DNS 域名解析,浏览器将URL解析出相对应的IP地址及端口号
  • 浏览器与服务器建立一条TCP链接
  • 浏览器向服务器发送一条请求报文
  • 服务器返回给浏览器一条http响应报文
  • 浏览器进行渲染
  • 关闭tcp链接

3. 强缓存和协商缓存

缓存是浏览器在本地磁盘对用户最近浏览的文档进行存储。

  • 强缓存:不会向服务器发送请求,直接从缓存中读取资源,在chrome控制台的network选项中可以看到该请求返回200的状态码;
  • 协商缓存:向服务器发送请求,服务器会根据这个请求的request header的一些参数来判断是否命中协商缓存,如果命中,则返回304状态码并带上新的response header通知浏览器从缓存中读取资源

4. 重绘(Repaint)和回流(Reflow)是啥?如何优化?

  • 重绘是当节点需要更改外观而不会影响布局的,比如改变 color 就叫称为重绘。

  • 回流是布局或者几何属性需要改变就称为回流。

  • 回流必定会发生重绘,重绘不一定会引发回流。回流所需的成本比重绘高的多,改变父节点里的子节点很可能会导致父节点的一系列回流。

    优化方案

使用 transform 替代 top 使用 visibility 替换 display: none ,因为前者只会引起重绘,后者会引发回流(改变了布局) 不要把节点的属性值放在一个循环里当成循环里的变量 不要使用 table 布局,可能很小的一个小改动会造成整个 table 的重新布局 动画实现的速度的选择,动画速度越快,回流次数越多,也可以选择使用requestAnimationFrame CSS 选择符从右往左匹配查找,避免节点层级过多 将频繁重绘或者回流的节点设置为图层,图层能够阻止该节点的渲染行为影响别的节点。比如对于 video 标签来说,浏览器会自动将该节点变为图层`

5. 同源策略是什么?

同源策略是指只有具有相同源的页面才能够共享数据,比如cookie,同源是指页面具有相同的协议、域名、端口号,有一项不同就不是同源。

6. webpack与grunt、gulp的不同?

  • Grunt、Gulp是基于任务运行的工具: 它们会自动执行指定的任务,就像流水线,把资源放上去然后通过不同插件进行加工,它们包含活跃的社区,丰富的插件,能方便的打造各种工作流。
  • Webpack是基于模块化打包的工具: 自动化处理模块,webpack把一切当成模块,当 webpack 处理应用程序时,它会递归地构建一个依赖关系图(dependency graph),其中包含应用程序需要的每个模块,然后将所有这些模块打包成一个或多个 bundle。

7.webpack中loader和plugin的区别

  • Loader直译为"加载器"。Webpack将一切文件视为模块,但是webpack原生是只能解析js文件,如果想将其他文件也打包的话,就会用到loader。 所以Loader的作用是让webpack拥有了加载和解析_非JavaScript文件_的能力。
  • Plugin直译为"插件"。Plugin可以扩展webpack的功能,让webpack具有更多的灵活性。 在 Webpack 运行的生命周期中会广播出许多事件,Plugin 可以监听这些事件,在合适的时机通过 Webpack 提供的 API 改变输出结果。
  • Loader在module.rules中配置,也就是说他作为模块的解析规则而存在。 类型为数组,每一项都是一个Object,里面描述了对于什么类型的文件(test),使用什么加载(loader)和使用的参数(options) Plugin在plugins中单独配置。 类型为数组,每一项是一个plugin的实例,参数都通过构造函数传入。

8.webpack的构建流程是什么?

Webpack 的运行流程是一个串行的过程,从启动到结束会依次执行以下流程:

  • 初始化参数:从配置文件和 Shell 语句中读取与合并参数,得出最终的参数;
  • 开始编译:用上一步得到的参数初始化 Compiler 对象,加载所有配置的插件,执行对象的 run 方法开始执行编译;
  • 确定入口:根据配置中的 entry 找出所有的入口文件;
  • 编译模块:从入口文件出发,调用所有配置的 Loader 对模块进行翻译,再找出该模块依赖的模块,再递归本步骤直到所有入口依赖的文件都经过了本步骤的处理;
  • 完成模块编译:在经过第4步使用 Loader 翻译完所有模块后,得到了每个模块被翻译后的最终内容以及它们之间的依赖关系;
  • 输出资源:根据入口和模块之间的依赖关系,组装成一个个包含多个模块的 Chunk,再把每个 Chunk 转换成一个单独的文件加入到输出列表,这步是可以修改输出内容的最后机会;
  • 输出完成:在确定好输出内容后,根据配置确定输出的路径和文件名,把文件内容写入到文件系统。

9.webpack的plugins和loaders的实现原理?

Loader像一个"翻译官"把读到的源文件内容转义成新的文件内容,并且每个Loader通过链式操作,将源文件一步步翻译成想要的样子。 编写Loader时要遵循单一原则,每个Loader只做一种"转义"工作。 每个Loader的拿到的是源文件内容(source),可以通过返回值的方式将处理后的内容输出,也可以调用this.callback()方法,将内容返回给webpack。 还可以通过 this.async()生成一个callback函数,再用这个callback将处理后的内容输出出去。 此外webpack还为开发者准备了开发loader的工具函数集——loader-utils。 相对于Loader而言,Plugin的编写就灵活了许多。webpack在运行的生命周期中会广播出许多事件,Plugin 可以监听这些事件,在合适的时机通过 Webpack 提供的 API 改变输出结果

10. 如何提高webpack的构建速度?

  • 多入口情况下,使用CommonsChunkPlugin来提取公共代码
  • 通过externals配置来提取常用库
  • 利用DllPlugin和DllReferencePlugin预编译资源模块 通过DllPlugin来对那些我们引用但是绝对不会修改的npm包来进行预编译,再通过
  • DllReferencePlugin将预编译的模块加载进来。
  • 使用Happypack 实现多线程加速编译
  • 使用webpack-uglify-parallel来提升uglifyPlugin的压缩速度。 原理上webpack-uglify-parallel采用了 多核并行压缩来提升压缩速度
  • 使用Tree-shaking和Scope Hoisting来剔除多余代码

11. AMD和CMD的区别?

最明显的区别就是在模块定义时对依赖的处理不同 AMD推崇依赖前置,在定义模块的时候就要声明其依赖的模块 CMD推崇就近依赖,只有在用到某个模块的时候再去require

12. 说一下你了解CSS盒模型

  1. 基本概念 标准模型 border margin padding content IE模型 border margin padding content

  2. 标准模型和IE模型的区别 计算width height 的不同 标准模型: width height 是content的高度 宽度 IE模型: width height 包含padding border部分

  3. css如何设置两种模型 标准: box-sizing: content-box IE模型: box-sizing :border-box

  4. js如何获取盒子模型对应的宽和高

document.style.width/height document.currentStyle.width/height window.getComputedStyle(dom).width

  1. BFC 块级格式化上下文,解决边距重叠 原理: 1)BFC垂直方向发生重叠 。 2)BFC的区域不会与浮动元素的box重叠 3)BFC是一个独立的容器,外面的元素不会影响里面的元素 。
    4)计算BFC高度,浮动元素也会参与计算

Javascript部分

1. 谈谈对闭包的理解,闭包的用途,闭包的缺点

  • 闭包是指有权访问另外一个函数作用域中的变量的函数
  • 闭包的用途
    1. 设计私有的方法和变量。
    2. 匿名函数最大的用途是创建闭包,并且还可以构建命名空间,以减少全局变量的使用。从而使用闭包模块化代码,减少全局变量的污染
  • 闭包的缺点
    1. 闭包会使得函数中的变量都被保存在内存中,滥用闭包可能导致内存泄漏。解决方法是在函数退出之前,将不使用的局部变量全删了。
    2. 闭包会在父函数外部,改变父函数内部变量的值。

2. 讲一讲js里面的异步操作有哪些?

 回调函数
 事件监听
 观察者模式,也叫订阅发布模式
 promise 
 async/await
 generator 函数

3. 什么是函数节流和函数去抖?

  • 函数去抖 debounce: 当调用函数n秒后,才会执行该动作,若在这n秒内又调用该函数则将取消前一次并重新计算执行时间。
var debounce = function(delay, cb) {
    var timer;
    return function() {
        if (timer) clearTimeout(timer);
        timer = setTimeout(function() {
            cb();
        }, delay);
    }
}
  • 函数节流 throttle: 函数节流的基本思想是函数预先设定一个执行周期,当调用动作的时刻大于等于执行周期则执行该动作,然后进入下一个新周期

    var throttle = function(delay, cb) {
    	var startTime = Date.now();
    	return function() {
    		var currTime = Date.now();
    		if (currTime - startTime > delay) {
    			cb();
    			startTime = currTime;
    		}
    	}
    }
    

 ### 4. script标签如何异步加载?
  * 默认情况下,浏览器是同步加载 JavaScript 脚本,即渲染引擎遇到 script 标签就会停下来,等到执行完脚本,再继续向下渲染。如果是外部脚本,还必须加入脚本下载的时间。如果脚本体积很大,下载和执行的时间就会很长,因此造成浏览器堵塞,用户会感觉到浏览器“卡死”了,没有任何响应。
 ```javascript
<script src="path/to/myModule.js" defer></script>
<script src="path/to/myModule.js" async></script>
- defer与async的区别是:
 1.  defer要等到整个页面在内存中正常渲染结束(DOM 结构完全生成,以及其他脚本执行完成),才会执行;async一旦下载完,渲染引擎就会中断渲染,执行这个脚本以后,再继续渲染。一句话,defer是“渲染完再执行”,async是“下载完就执行”。
 2. 另外,如果有多个defer脚本,会按照它们在页面出现的顺序加载,而多个async脚本是不能保证加载顺序的。

5. 讲一下let、var、const的区别,谈谈如何冻结变量

  • var 没有块级作用域,支持变量提升。
  • let 有块级作用域,不支持变量提升。不允许重复声明,暂存性死区。
  • const 有块级作用域,不支持变量提升,不允许重复声明,暂存性死区。声明一个变量一旦声明就不能改变,改变报错。const保证的变量的内存地址不得改动。如果想要将对象冻结的话,使用Object.freeze()方法

6. 谈谈js事件循环机制

  • 程序开始执行之后,主程序则开始执行 同步任务,碰到 异步任务 就把它放到任务队列中,等到同步任务全部执行完毕之后,js引擎便去查看任务队列有没有可以执行的异步任务,将异步任务转为同步任务,开始执行,执行完同步任务之后继续查看任务队列,这个过程是一直 循环 的,因此这个过程就是所谓的 事件循环,其中任务队列也被称为事件队列。通过一个任务队列,单线程的js实现了异步任务的执行,给人感觉js好像是多线程的。

7.箭头函数和普通函数的区别是什么?

  • 普通函数this:
    1. this总是代表它的直接调用者。
    2. 在默认情况下,没找到直接调用者,this指的是window。
    3. 在严格模式下,没有直接调用者的函数中的this是undefined。
    4. 使用call,apply,bind绑定,this指的是绑定的对象。
  • 箭头函数this:
    1. 在使用=>定义函数的时候,this的指向是 定义时所在的对象,而不是使用时所在的对象;
    2. 不能够用作构造函数,这就是说,不能够使用new命令,否则就会抛出一个错误;
    3. 不能够使用 arguments 对象;
    4. 不能使用 yield 命令;

8. 函数柯里化理解

  • 只传递给函数一部分参数来调用它,让它返回一个函数去处理剩下的参数。
  • 用途:1.延迟计算;2.参数复用;3.动态生成函数

9. new 内部发生了什么过程?可不可以手写实现一个 new 操作符?

  • 创建一个新的对象
  • 这个对象的__proto__ 指向原函数的prototype属性
  • 将这个新对象绑定到这个函数的this上
  • 返回新对象,如果这个函数没有返回其他对象

10. new/字面量 与 Object.create(null) 创建对象的区别?

new 和 字面量创建的对象的原型指向 Object.prototype,会继承 Object 的属性和方法。 而通过 Object.create(null) 创建的对象,其原型指向 null,null 作为原型链的顶端,没有也不会继承任何属性和方法。

框架类 (React)

1. 为什么虚拟dom会提高性能

  • 虚拟dom相当于在js和真实dom中间加了一个缓存,利用dom diff算法避免了没有必要的dom操作,从而提高性能,虚拟DOM本质上是JavaScript对象,是对真实DOM的抽象,状态变更时,记录新树和旧树的差异,最后把差异更新到真正的dom中

具体实现步骤如下:

  1. 用 JavaScript 对象结构表示 DOM 树的结构;然后用这个树构建一个真正的 DOM 树,插到文档当中;
  2. 当状态变更的时候,重新构造一棵新的对象树。然后用新的树和旧的树进行比较,记录两棵树差异; 把2所记录的差异应用到步骤1所构建的真正的DOM树上,视图就更新了

前端的性能优化和安全

1. 常见的网站漏洞有哪些

有跨站脚本攻击(XSS)、跨站请求伪造(CSRF)、点击劫持、SQL注入、DDOS攻击、DNS劫持

2. 讲讲CSRF和XSS区别

XSS:跨站点攻击。xss攻击的主要目的是想办法获取目标攻击网站的cookie,因为有了cookie相当于有了session,有了这些信息就可以在任意能接进互联网的PC登陆该网站,并以其他人的身份登陆做破坏。

CSRF 跨站点伪装请求

xss和csrf有哪些防御方式

如何防范 XSS 攻击: 1、对输入的字符串做长度限制; 2、对用户的输入进行过滤,如对& < > " ' /等进行转义; 3、获取用户的输入,不用innerHtml,用innerText.

如何防范CSRF攻击: 1、验证 HTTP Referer 字段; 2、在请求地址中添加 token 并验证; 3、在 HTTP 头中自定义属性并验证。

HTML5

1. Html5语义化与新特性

1、什么是HTML语义化?

  • 表示选择合适的标签(语义化标签)便于开发者阅读和写出更优雅的代码

2、为什么要使用语义化标签? 在没有CSS样式的情况下,页面整体也会呈现很好的结构效果 更有利于用户体验 更有利于搜索引擎优化 代码结构清晰,方便团队开发与维护

3、 HTML5新特性有哪些? 语义化标签 音视频处理 canvas / webGL history API requestAnimationFrame 地理位置 webSocket

DOM事件类

1. 基本概念:DOM事件的级别

DOM0:element.onlick = function(){}
DOM2:element.addEventListener('click', function(){},false)
DOM3:element.addEventListener('keyup',function(){},false)

2. DOM事件模型

冒泡事件是从内向外 捕获是从外向内======document->html->body->div

3. DOM事件流

一个完整的事件流分为三个阶段:捕获-》目标阶段-》冒泡=========事件通过捕获到达目标元素再从目标元素通过冒泡上传到元素 捕获:window->document->html->body->......->目标元素

对象深浅拷贝

1. 浅拷贝

创建一个新对象,这个对象有着原始对象属性值的一份精确拷贝。如果属性是基本类型,拷贝的就是基本类型的值,如果属性是引用类型,拷贝的就是内存地址 ,所以如果其中一个对象改变了这个地址,就会影响到另一个对象

Object.assign(target, ...sources)

2. 深拷贝

将一个对象从内存中完整的拷贝一份出来,从堆内存中开辟一个新的区域存放新对象,且修改新对象不会影响原对象

最简单的方法就是JSON.parse(JSON.stringify()),但是这种拷贝方法不可以拷贝一些特殊的属性(例如正则表达式,undefine,function)

```javascript
function deepCopyTwo(obj) {
	let objClone = Array.isArray(obj) ? [] : {};
	if (obj && typeof obj == 'object') {
		for (const key in obj) {
			//判断obj子元素是否为对象,如果是,递归复制
			if (obj[key] && typeof obj[key] === "object") {
				objClone[key] = deepCopyTwo(obj[key]);
			} else {
				//如果不是,简单复制
				objClone[key] = obj[key];
			}
		}
	}
	return objClone;
}

```

bind、call、apply用法及区别

相同点: 三个函数的作用就是改变this的指向,将函数绑定到上下文中; 不同点: 三个函数的语法不同

```javascript
fun.call(thisArg[, arg1[, arg2[, ...]]])
fun.apply(thisArg, [argsArray])
var bindFn = fun.bind(thisArg[, arg1[, arg2[, ...]]])
bindFn()
```

目前JS解决异步的方案有哪些

  • 回调函数
  • 事件监听
  • 发布-订阅
  • Promise
  • Generator
  • Async/Await

创建对象有几种方法

// 第一种:字面量
var o1 = {name: "o1"}
var o2 = new Object({name: "o2"})
// 第二种:通过构造函数
var M = function(name){this.name = name}
var o3 = new M("o3")
// 第三种:Object.create()
var p = {name: "p"}
var o4 = Object.create(p)

浏览器篇

1.跨域解决方案

1) jsonp

  1. 原理 利用script标签没有跨域限制的漏洞,网页可以得到从其他来源动态产生的 JSON 数据。JSONP请求一定需要对方的服务器做支持才可以
  2. JSONP和AJAX对比 JSONP和AJAX相同,都是客户端向服务器端发送请求,从服务器端获取数据的方式。但AJAX属于同源策略,JSONP属于非同源策略(跨域请求)
  3. JSONP优缺点 JSONP优点是简单兼容性好,可用于解决主流浏览器的跨域数据访问的问题。缺点是仅支持get方法具有局限性,不安全可能会遭受XSS攻击。

2)cors

3)postMessage

4)websocket

5)Node中间件代理(两次跨域)

6)nginx反向代理

7)window.name + iframe

8)document.domain + iframe