本人做前端开发四年有余,最近准备出去看看机会,由于很久没面试,js很多基础问题都忘记了很多,本人决定总结一下基本会问到的基础性问题,由于水平有限,答案可能会有错误,望各位大佬指出,请勿喷,谢谢!
1,js原型链以及有哪些方式可以实现继承
答:每个对象拥有一个原型对象,通过 proto 隐士属性指针指向上一个原型 ,并从中继承方法和属性,同时原型对象也可能拥有原型,这样一层一层,最终指向 null。这种关系被称为原型链
继承实现的方式:
- 原型继承 缺点:原型链继承里面使用的是同一个内存值,这样修改的改内存值,其他继承的子类实现都会被修改
- 构造函数继 优点:避免了引用类型的属性被所有实例共享 可以在子类向父类传参 缺点:方法都在构造函数中定义,每次创建实例都会创建一遍方法
- es6 exends继承
- 寄生组合式继承
2,es6继承实现的原理
答:ES6中,子类中,super方法是必须调用的,因为子类本身没有自身的this对象,需要通过super方法拿到父类的this对象。在子类中,没有构造函数,那么在默认的构造方法内部自动调用super方法,继承父类的全部属性,子类的构造方法中,必须先调用super方法,然后才能调用this关键字声明其它属性。(子类的this就是在这里调用super之后,拿到父类的this,然后修改这个this来的)
3,async和await实现原理
答:它实现的原理就是通过Generator函数语法糖 async函数就是将Generato函数的星号(*)替换成async 将yield替换成await而已,await命令就是then命令的语法糖
4,var,const以及let的区别,以及let和const作用域是如何划分的
- var 和 let 第一点不同就是 let 是块作用域 var只有全局作用域和函数作用域概念,没有块级作用域的概念
- let 和 var 的第二点不同是,在变量声明之前就访问变量的话,会直接提示ReferenceError,而不像 var 那样使用默认值 undefined
- let不允许重复声明变量
- const 和 let 的作用域是一致的,不同的是 const 变量一旦被赋值,就不能再改变了,但是这并不意味着使用 const 声明的变量本身不可变,只是说它不可被再次赋值了,而且const 声明的变量必须经过初始化 是通过代码块,if语句等划分
5,防抖和节流的区别以及应用的场景
防抖和节流:
- 相同点:在不影响客户体验的前提下,将频繁的回调函数,进行次数缩减.避免大量计算导致的页面卡顿.
- 不同点:防抖是将多次执行变为最后一次执行,节流是将多次执行变为在规定时间内只执行一次 防抖:指触发事件后在规定时间内回调函数只能执行一次,如果在规定时间内又触发了该事件,则会重新开始算规定时间。
四个字总结就是 延时执行
应用场景: 输入搜索联想,用户在不断输入值时,用防抖来节约请求资源。按钮点击:收藏,点赞,心标等
节流:当持续触发事件时,在规定时间段内只能调用一次回调函数。如果在规定时间内又触发了该事件,则什么也不做,也不会重置定时器.
节流防抖总结:防抖是将多次执行变为最后一次执行,节流是将多次执行变为在规定时间内只执行一次.一般不会重置定时器
应用场景: 鼠标不断点击触发,点击事件在规定时间内只触发一次(单位时间内只触发一次)。监听滚动事件,比如是否滑到底部自动加载更多,用throttle来判断
6,js有哪几种作用域?
答:全局作用域和局部作用域以及es6块级作用域
7,event loop执行机制
-
- 一开始整个脚本作为一个宏任务执行
-
- 执行过程中同步代码直接执行,宏任务进入宏任务队列,微任务进入微任务队列
-
- 当前宏任务执行完出队,检查微任务列表,有则依次执行,直到全部执行完
-
- 执行浏览器UI线程的渲染工作
-
- 检查是否有Web Worker任务,有则执行
-
- 执行完本轮的宏任务,回到2,依此循环,直到宏任务和微任务队列都为空 ###### 微任务包括:
MutationObserver、Promise.then()或catch()、Promise为基础开发的其它技术,比如fetch API、V8的垃圾回收过程、Node独有的process.nextTick。
宏任务包括: script 、setTimeout、setInterval 、setImmediate 、I/O 、UI rendering
8,词法作用域是什么
答:所谓的 词法( 代码 )作用域, 就是代码在编写过程中体现出来的作用范围. 代码一旦写好, 不用执行,作用范围就已经确定好了. 这个就是所谓词法作用域。
在 js 中词法作用域规则: 函数允许访问函数外的数据.整个代码结构中只有函数可以限定作用域. 作用规则首先使用提升规则分析,如果当前作用规则中有名字了, 就不考虑外面的名字。
9,什么是闭包,闭包的应用场景有哪些?
答:闭包是指有权访问另一个函数作用域中的变量的函数。创建闭包的方式,就是在函数内部创建另一个函数。 闭包的应用场景在es5里面就是起到管理全局以及局部作用域而已,现在开发框架基本用不到
10,什么是执行栈
答:执行栈,在其他编程语言中也被称为“调用栈”,这是一种后进先出(LIFO)的数据结构,被用来储存在代码运行阶段创建的所有的执行上下文。 当Javascript引擎(译者注:Javascript引擎是执行Javascript代码的解释器,一般被内嵌在浏览器中)开始执行你第一行Javascript脚本代码的时候,它就会创建一个全局执行上下文然后将它压到执行栈中。每当引擎碰到一个函数的时候,它就会创建一个函数执行上下文,然后将这个执行上下文压到执行栈中。(译者注:这种结构类似弹夹,执行栈就是弹夹,执行上下文是子弹,子弹被一个个压入弹夹,当子弹发射的时候,最后一个进弹夹的子弹会被最先射出)。 引擎会执行位于执行栈栈顶的执行上下文(一般是函数执行上下文),当该函数执行结束后,对应的执行上下文就会被弹出,然后控制流程到达执行栈的下一个执行上下文。
11,执行.then会发生什么
答:会先判断状态是pending还是别的状态,一旦是另外的状态是不可逆的
12,如何实现多线程
答:Web Worker 的作用,就是为 JavaScript 创造多线程环境,允许主线程创建 Worker 线程,将一些任务分配给后者运行。在主线程运行的同时,Worker 线程在后台运行,两者互不干扰。等到 Worker 线程完成计算任务,再把结果返回给主线程。这样的好处是,一些计算密集型或高延迟的任务,被 Worker 线程负担了,主线程(通常负责 UI 交互)就会很流畅,不会被阻塞或拖慢。
13,js基本类型有哪些,基本类型与引用类型的区别?
答:null undefinde number string boolean symbol六大类型 区别:基本数据类型使用值(value)的方式进行比较 基本数据类型使用值(value)的方式进行传递 引用类型通过引用(reference)进行比较 判断基本类型与引用类型的方法不一样
14,判断对象有哪些方法
- 用instanceof
- constructor方法
- 利用tostring()方法,这个方法是最佳的方案, Object.prototype.toString.call(a)
15,深拷贝浅拷贝区别
答:深拷贝和浅拷贝最根本的区别在于是否是真正获取了一个对象的复制实体,而不是引用, 深拷贝在计算机中开辟了一块内存地址用于存放复制的对象,而浅拷贝仅仅是指向被拷贝的内存地址,如果原地址中对象被改变了,那么浅拷贝出来的对象也会相应改变。
16,封装实现深拷贝的方法需要注意什么
答:考虑数据类型,兼容数组解决循环引用问题
解决循环引用问题,我们可以额外开辟一个存储空间,来存储当前对象和拷贝对象的对应关系,当需要拷贝当前对象时,先去存储空间中找,有没有拷贝过这个对象,如果有的话直接返回,如果没有的话继续拷贝,这样就巧妙化解的循环引用的问题。这个存储空间,需要可以存储key-value形式的数据,且key可以是一个引用类型,我们可以选择Map这种数据结构
17,call,apply和bind区别
答:call只能一个一个参数传入,apply只能支持传入一个数组形式,call ,apply在函数调用时给绑定this 而bind是在函数进行调用之前强行绑定this bind支持参数一个一个传入
18,箭头函数this和es5的this有何区别,如何改变箭头函数指向
- 函数体内的this对象就是定义时所在的对象,而不是使用时所在对象
- 不可以使用new命令,否则会抛出错误
- 不可以使用argument对象,该对象在函数体内不存在,如果要用可以用rest参数代替
- 不可以使用apply,call或者bind改变指向,用了也不会改变指向,也不会报错
- 改变箭头函数指向就是改变函数的执行上下文
19,说说事件流,它的工作流程是咋样的
答:事件流包括三个阶段:事件捕获阶段,处于目标阶段,事件冒泡阶段
绑定事件的方法:onclick addEventListener: 接收三个参数 第一事件类型,第二事件方法,第三是事件流按事件捕获还是事件冒泡 如果是false,表示冒泡阶段处理,是true表示捕获阶段处理
20,New promise实现原理
答:首先构造一个promise对象函数,里面先初始化需要用到的参数,比如状态 pending, resolve, rejected 三个状态 然后封装resolve方法 rejected等方法
21,重汇和回流如何理解
答:回流这一阶段主要是计算节点的位置和几何信息,那么当页面布局和几何信息发生变化的时候,就需要回流 比如以下情况:
- 添加或删除可见的DOM元素
- 元素的位置发生变化
- 元素的尺寸发生变化(包括外边距、内边框、边框大小、高度和宽度等)
- 内容发生变化,比如文本变化或图片被另一个不同尺寸的图片所替代。
- 页面一开始渲染的时候(这肯定避免不了)
- 浏览器的窗口尺寸变化(因为回流是根据视口的大小来计算元素的位置和大小的) 注意:回流一定会触发重绘,而重绘不一定会回流
当页面中元素样式的改变并不影响它在文档流中的位置时(例如:color、background-color、visibility等),浏览器会将新样式赋予给元素并重新绘制它,这个过程称为重绘。
22,同步异步的区别
答:同步任务指的是,在主线程上排队执行的任务,异步指的是不进入主线程,而进入任务队列
23,New 一个对象发生什么
- 创建一个新的对象
- 连接到原型
- 绑定this的指向
- 返回新的对象
24,Es6中map和set数据结构有什么作用
答:set类似于数组,成员值都是唯一的,没有重复值,set本身是一个构造函数,用来生成set数据结构 Map类似于对象,也是健值对的集合,但是健的范围不限于字符串,各种类型的值都可以当作键。
map结构提供了值一值的对应,是一种更完善的hash结构实现
25,Es6中查找数组包含某个属性的是哪个方法
答:some和every方法
26,Map和foreach区别
答:forEach()会改变原始的数组的值,而map()会返回一个全新的数组,原本的数组不受到影响 Map执行速度比forEach慢
27,Js操作数组和字符串有哪些方法
- pop() 删除数组中最后一个元素
- Shift() 删除数组的第一个元素
- Push() 向数组末尾添加元素
- Unfit() 向数组开头添加元素
- Reverse 颠倒数组中元素排序
- Fill填充 以上改变原数组方法
- Slice() 浅拷贝数组元素
- Join数组转字符串
- Tolocalestring 数组转字符串
- Tostring数组转字符串 不能自定义分隔符
- Cancat 合并多个数组 返回新数组
- IndexOf 查找数组存在某一元素
- Lastindexof 查找指定元素在某一位置
- Includes 查找数组是否包含某个元素 以上方法可以返回新数组
28,说说执行上下文,作用域以及作用域链的概念
作用域:JavaScript 采用词法作用域(lexical scoping),函数执行依赖的变量作用域是由函数定义的时候决定,而不是函数执行的时候决定 JavaScript 中全局变量拥有全局的作用域,函数体内申明的变量的作用域是整个函数体内,是局部的,当然也包括函数体内定义的嵌套函数。函数体内局部变量的优先级高于全局变量,如果局部变量与全局变量重名,全局变量会被局部变量掩盖;同样嵌套函数内定义的局部变量的优先级高于嵌套函数所在函数的局部变量
作用域链:每当创建一个函数的时候,那么js会自己为这个函数创建一个预先包含全局变量对象的作用域链,然后把这个作用域链保存在内部的[[Scope]]属性中,当这个函数被调用的时候,首先就会将这个函数的执行环境添加到环境栈中,,然后通过复制函数的[[Scope]]属性中的对 象就可以构建起执行环境的作用域链 执行上下文:函数执行前进行的准备工作(也称执行上下文环境) JavaScript中执行环境 全局环境, 函数环境, eval函数环境 (已不推荐使用) 执行上下文的类型: 全局执行上下文,函数执行上下文 evel函数执行上下文
29,AddEventListener有几个参数,它们的作用是什么
答:事件名称(String)、要触发的事件处理函数(Function)、指定事件处理函数的时期或阶段(boolean)
30,js扁平化数组有哪些方法
- flat() // 不传参数时,默认“拉平”一层
- flat(2) // 传入一个整数参数,整数即“拉平”的层数
- flat(Infinity) // Infinity 关键字作为参数时,无论多少层嵌套,都会转为一维数组
31,node.js的优缺点
优点: 高并发(最重要的优点)适合I/O密集型应用
缺点:不适合CPU密集型应用;CPU密集型应用给Node带来的挑战主要是:由于JavaScript单线程的原因,如果有长时间运行的计算(比如大循环),将会导致CPU时间片不能释放,使得后续I/O无法发起;
32,js严格模式与非严格模式区别
答:严格模式中,对象直接量中定义同名属性会抛出语法错误; 非严格模式不会报错 严格模式中,函数形参存在同名的,抛出错误; 非严格模式不会 严格模式中,arguments对象是传入函数内实参列表的静态副本;非严格模式下,arguments对象里的元素和对应的实参是指向同一个值的引用 严格模式 变量必须先声明,直接给变量赋值,不会隐式创建全局变量,不能用with, 严格模式中 call apply传入null undefined保持原样不被转换为window
33,Js中有哪些操作会造成内存泄露
- 意外的全局变量引起的内存泄露
- 闭包引起的内存泄露
- 没有清除的定时器
34,js序列化和反序列化
答:序列化: 即js中的Object转化为字符串,可以使用toJSONString以及JSON.stringify(obj) 反序列化: 即js中JSON字符串转化为Object可以使用parseJSON以及使用eval
35,单线程和多线程区别,js是单线程还是多线程,以及单线程执行顺序
答:线程:简单的说就是处理事务的任务链,当只有一条链,所有的事情都在这一条链上执行时,那就是单线程 而当有多条链时,那就是多线程了,当然并不是说多条线并行,而是说有一条主线程,处理整个程序任务的主方向的链,而其链上又有许许多多的分支
单线程执行顺序:js是单线程,它只能够处理同步任务,异步任务是需要浏览器线程执行,主线程在执行过程中遇到了异步任务,就发起函数或者称为注册函数,通过event loop线程通知相应的工作线程(如ajax,dom,setTimout等),同时主线程继续向后执行,不会等待。等到工作线程完成了任务,eventloop线程会将消息添加到消息队列中,如果此时主线程上调用栈为空就执行消息队列中排在最前面的消息,依次执行。新的消息进入队列的时候,会自动排在队列的尾端。
36,微前端是什么
答:微前端是一种类似于微服务的架构,它将微服务的理念应用于浏览器端,即将 Web 应用由单一的单体应用转变为多个小型前端应用聚合为一的应用。各个前端应用可以独立运行、独立开发、独立部署。
优点:可以与时俱进,不断引入新技术/新框架 局部/增量升级 代码简洁、解耦、更易维护 独立部署 组织更具扩展能力,其团队更加独立自治。
缺点:重复依赖,团队之间更加分裂