面试题总结

187 阅读7分钟

1、JS 的基本数据类型、引用类型,二者存储的方式
基本数据类型存放在栈中,引用数据类型存放在堆中
2、说一下 event loop
执行栈在执行完同步任务后,检查执行栈是否为空,如果为空,检查微任务队列是否为空,如果微任务队列不为空,则一次性执行完所有的微任务。如果微任务为空,则去执行下一个宏任务。 每次单个的宏任务执行完之后,都会检查微任务队列是否为空,如果不为空,则按照先进先出的方式执行完所有的微任务,然后执行下一个宏任务,以此循环。
3、JS 事件循环和 Node.js 的事件循环的区别
Node 中的 Event Loop 和浏览器中的是完全不相同的东西。Node.js 采用 V8 作为 js 的解析引擎,而 I/O 处理方面使用了自己设计的 libuv,libuv 是一个基于事件驱动的跨平台抽象层,封装了不同操作系统一些底层特性,对外提供统一的 API,事件循环机制也是它里面的实现(下文会详细介绍)。 浏览器和 Node 环境下,microtask 任务队列的执行时机不同

  • Node 端,microtask 在事件循环的各个阶段之间执行
  • 浏览器端,microtask 在事件循环的 macrotask (微任务)执行完之后执行 4、ES6 的新特性(这里讲的很细)

解决原有语法上的不足
let const
对原有语法进行增强
解构,展开,参数默认值,模板字符串
全新的对象、全新的方法、全新的功能
promise,proxy,object的assign,is。箭头函数
全新的数据结构
set,map,symbol

5、ES6 的模块化和 CommonJS 模块化的区别
commonjs是nodejs中自带的模块化 module.exports require
es6引入的模块化。支持import来引入另一个js
export命令用于规定模块的对外接口,import命令用于输入其他模块提供的功能。
CommonJS 模块输出的是一个值的拷贝,ES6 模块输出的是值的引用。

  • CommonJS 模块输出的是值的拷贝,也就是说,一旦输出一个值,模块内部的变化就影响不到这个值。

  • ES6 模块的运行机制与 CommonJS 不一样。JS 引擎对脚本静态分析的时候,遇到模块加载命令import,就会生成一个只读引用。等到脚本真正执行时,再根据这个只读引用,到被加载的那个模块里面去取值。换句话说,ES6 的import有点像 Unix 系统的“符号连接”,原始值变了,import加载的值也会跟着变。因此,ES6 模块是动态引用,并且不会缓存值,模块里面的变量绑定其所在的模块。

CommonJS 模块是运行时加载,ES6 模块是编译时输出接口。

  • 运行时加载: CommonJS 模块就是对象;即在输入时是先加载整个模块,生成一个对象,然后再从这个对象上面读取方法,这种加载称为“运行时加载”。
  • 编译时加载: ES6 模块不是对象,而是通过 export 命令显式指定输出的代码,import时采用静态命令的形式。即在import时可以指定加载某个输出值,而不是加载整个模块,这种加载称为“编译时加载”。

CommonJS 加载的是一个对象(即module.exports属性),该对象只有在脚本运行完才会生成。而 ES6 模块不是对象,它的对外接口只是一种静态定义,在代码静态解析阶段就会生成。

点击这里查看详细介绍

8、import 和 require 的最主要的区别,静态引用和动态引用
动态编译
第一次加载某个模块时, Node会缓存该模块, 后续加载就从缓存中获取。

require是运行时调用,所以require理论上可以运用在代码的任何地方。 静态编译
ES6模块的编译: import模块时只是生成引用, 等到需要时才去取值, 所以不存在缓存的问题, 而且模块里的变量, 绑定其所在的模块。

import是编译时调用,虽然import命令具有提升效果,会提升到整个模块的头部, 但还是建议放在文件开头。
9、promise 和 await async 之间的关系
async和awit是es8提出来的。async旨在利用异步结构组织代码问题。 anync可以让函数具有异步特征,但总体上代码还是同步求值的。如果函数使用return返回了值,这个函数会被promise.resolve()包装成一个期约对象。异步函数始终返回期约对象。
await可以暂停异步函数代码的执行,等待期约解决。
js在运行时再碰到await的时候,会记录在哪里暂停执行。等到await右边的值可以用了,js运行时会向消息队列中推送一个任务,这个任务会恢复异步函数的执行。

10、说一下 promise 的三种状态
pending resolved rejected

11、讲一下 ES6 继承 extend
语法糖,实际还是通过原型链继承。extend可以继承一个类,也可以继承一个构造函数。在类构造函数中使用super可以调用父类构造函数。

12、有用过 extend 继承吗?你父类中写的是什么东西呢?

13、讲一下 ES6 之前的继承方式(6 种,一个一个讲的)
1>,盗用构造函数:在子类构造函数中调用父类的构造函数。
缺点:必须在构造函数中定义方法,函数不能重用。
2>,原型链继承:子类通过创建父类的实例并将其赋值给自己的原型实现了对父类的继承。
缺点:原型中包含的引用值会在所有实例间共享
3>,组合继承:综合了以上两者,使用原型链继承原型上的属性和方法,而通过盗用构造函数继承实例属性。这样既可以把方法定义在原型上以实现重用,又可以让每个实例都有自己的属性。
4>原型式继承:在一个函数内部,先创建了一个临时的构造函数,然后将传入的对象作为该构造函数的原型,最后返回了这个临时类型的新实例。
5>寄生式继承:创造一个实现继承的函数,以某种方式增强对象,然后返回这个对象。
6>寄生式组合继承寄生式组合继承通过盗用构造函数继承属性,使用混合式原型链继承方法。基本思路是不通过调用父类构造函数给子类原型赋值,而是取得父类原型的一个副本。说到底就是使用寄生式继承来继承父类原型,然后将返回的新对象赋值给子类原型。

14、自己讲一下对 vue 的理解,自己讲用到的 vue 的功能
vue数据双向绑定是通过数据劫持结合发布者-订阅者模式的方式来实现的 15、vue2 中数据双向绑定使用到的 Object.define Proto type 如何做的依赖收集?
16、依赖收集在哪一个方法中去完成的?
17、说一下 dep 和 watcher 之间的关系
18、双向绑定的功能是在哪一个生命周期中实现的?
19、做 项目 有没有封装一些组件?
20、对 axios 的分析,比如添加中间件的能力(我答的相响应劫持这类的)
21、vue 模板编译的过程,每一个过程细说一下做了些什么
22、vue 实现 nextTick 原理

23、讲一下了解过的 webpack
24、讲一下 webpack 的核心概念,比如 loader、plugin、babel 等

25、http 缓存类型有哪些?
强缓存和协商缓存:
26、Etag 是 http 哪个版本出来的?它出来是为了解决什么问题?
6.vue响应式原理,计算属性原理,侦听器原理三连
8.promise.all .allSettled .race
2.nextTick作用和实现原理(promise Mutation Observer setImmediate 处理异步任务栈和兼容的降级处理)