大厂前端面试题总结(JS理论篇)

系列文章

  • 大厂前端面试题总结(CSS篇)
  • 大厂前端面试题总结(ES6篇)
  • 大厂前端面试题总结(浏览器篇)
  • 大厂前端面试题总结(性能优化篇)
  • 大厂前端面试题总结(JS手写篇)
  • 大厂前端面试题总结(Web安全篇)
  • 大厂前端面试题总结(Vue篇)

前言

本片文章如题主要讲解浏览器相关面试题,每道面试题都是从网上找的参考资料整理而来,侵删。部分未添加原文链接(如果想要了解面试题的更多信息,只需要点击每道面试后面的参考链接即可);
这一系列纯粹是为了个人面试整理的,为了圆一下二流学生的大厂梦!
双击标题可快速上下切换内容呦!
本文内容持续更新中,如果您认为不错,还请点赞收藏下哦!

JS

目录

  • 一、什么是DOM、BOM
  • 二、事件循环
  • 三、什么是闭包
  • 四、JS中apply、call和bind的区别
  • 五、Js原型和原型链
  • 六、JS实现继承的方法
  • 七、JS又那些内置对象
  • 八、JS操作数组的方法(Array对象属性)
  • 九、JS基本数据类型(2021.2.1)
  • 十、JS基本数据类型(2021.3.3)

一、什么是DOM、BOM

BOM

  • BOM即浏览器对象模型,是在客户端脚本核心的基础上实现的扩展API,通过该API可以使用脚本访问浏览器窗口及其文档对象的各个方面。
  • Window对象其实是BOM中所有对象的核心对象,所有的对象都源自window对象,它表示整个浏览器出口。
  • 在BOM API中,把WEB浏览器的各个主要外显特性、WEB页面及其标记、内容等都封装成一个对象,通过这些对象提供的成员访问窗口、文档、元素对象等,并在此基础上实现了对象的事件支持机制。所有BOM对象之间存在一定的关联关系。
  • 学习BOM技术主要就是学习如何利用客户端脚本使用BOM对象,通过这些封装的BOM对象可实现很多DHTML功效。BOM技术不是标准化的WEB技术,因浏览器而异。 正因为如此大大限制了DHTML技术的应用领域与发展前景。不同浏览器实现的BOM技术并不统一,这是造成DHTML技术实现差异的主要原因,由此W3C在BOM技术的基础上进行扩充和完善、优化,制定了新的统一技术规范标准,即DOM文档对象模型技术。

DOM

  • DOM技术最初是针对XML文档的解析与控制而制定的技术规范,它可把HTML文档XML转化成XHTML文档,使用DOM技术来访问WEB页面文档中的各类对象。
  • DOM技术与XML技术密切相关,涉及的技术内容庞杂,学习难度较高,但掌握了BOM技术后再学习DOM技术有一定的帮助。

二、事件循环

众所周知,JavaScript 是一门单线程语言,虽然在 html5 中提出了 Web-Worker ,但这并未改变 JavaScript 是单线程这一核心

为了协调事件、用户交互、脚本、UI 渲染和网络处理等行为,用户引擎必须使用事件循环。事件循环包含两类:一类是基于浏览器上下文,一种是基于Worker,二者是独立运行的。

下面本文用一个例子,着重讲解下基于 Browsing Context 的事件循环机制。
来看下面这段 JavaScript 代码:

console.log('script start');

setTimeout(function() {
  console.log('setTimeout');
}, 0);

Promise.resolve().then(function() {
  console.log('promise1');
}).then(function() {
  console.log('promise2');
});

console.log('script end');

// 结果如下:
// script start
// script end
// promise1
// promise2
// setTimeout

任务队列

浏览器上下文中所有的任务可以分为同步任务和异步任务。

  • 同步任务,顾名思义,就是立即执行的任务,同步任务一般会直接进入到主线程中执行
  • 异步任务,就是异步执行的任务,比如ajax网络请求,setTimeout 定时函数等都属于异步任务,异步任务会通过任务队列( Event Queue )的机制来进行协调。

具体的可以用下面的图来大致说明一下:
大厂前端面试题总结(JS理论篇)_第1张图片

同步和异步任务分别进入不同的执行环境,同步的进入主线程,即主执行栈,异步的进入 Event Queue 。主线程内的任务执行完毕为空,会去 Event Queue 读取对应的任务,推入主线程执行。 上述过程的不断重复就是我们说的 Event Loop (事件循环)。

在事件循环中,每进行一次循环操作称为tick,通过阅读规范可知,每一次 tick 的任务处理模型是比较复杂的,其关键的步骤可以总结如下:

  • 在此次 tick 中选择最先进入队列的任务( oldest task ),如果有则执行(一次)
  • 检查是否存在 Microtasks ,如果存在则不停地执行,直至清空Microtask Queue
  • 更新 render
  • 主线程重复执行上述步骤

可以用一张图来说明下流程:
大厂前端面试题总结(JS理论篇)_第2张图片
这里相信有人会想问,什么是 microtasks ?

规范中规定,task分为两大类, 分别是 Macro Task (宏任务)和 Micro Task(微任务), 并且每个宏任务结束后,都要清空所有的微任务,这里的 Macro Task也是我们常说的 task ,有些文章并没有对其做区分,后面文章中所提及的task皆看做宏任务( macro task)。

  • macrotask 主要包含:script(整体代码)setTimeoutsetIntervalI/OUI交互事件setImmediate(Node.js 环境)

  • microtask主要包含:PromiseMutaionObserverprocess.nextTick(Node.js 环境)

setTimeout/Promise 等API便是任务源,而进入任务队列的是由他们指定的具体执行任务。来自不同任务源的任务会进入到不同的任务队列。其中 setTimeout 与 setInterval 是同源的。

参考链接

三、什么是闭包

闭包(closure)

是一个受到保护的变量空间,由内嵌函数生成。JavaScript具有函数级的作用域。这意味着定义在函数内部的变量在函数外部不能被访问。JavaScript的作用域又是词法性质的。这意味着函数运行在定义它的作用域中,而不是调用它的作用域中。把这两个因素结合起来,就能通过把变量包裹在匿名函数中而对其加以保护。
各种专业文献的闭包定义都非常抽象,我的理解是: 闭包就是能够读取其他函数内部变量的函数。简单的闭包实现:

function foo(a) {
	return function(b) {
		return a+b;
	}
}

foo(1)(2) // 3

由于在javascript中,只有函数内部的子函数才能读取局部变量,所以说,闭包可以简单理解成定义在一个函数内部的函数
所以,在本质上,闭包是将函数内部和函数外部连接起来的桥梁。

优点

  1. 逻辑连续,当闭包作为另一个函数调用的参数时,避免你脱离当前逻辑而单独编写额外逻辑。
  2. 方便调用上下文的局部变量。
  3. 加强封装性,第2点的延伸,可以达到对变量的保护作用。

缺点

闭包有一个非常严重的问题,那就是内存浪费问题,这个内存浪费不仅仅因为它常驻内存,更重要的是,对闭包的使用不当会造成无效内存的产生。

四、JS中apply、call和bind的区别

在JS中,这三者都是用来改变函数的this对象的指向的,他们有什么样的区别呢。

在说区别之前还是先总结一下三者的相似之处:

1、都是用来改变函数this对象的指向的。

2、第一个参数都是this要指向的对象。

3、都可以利用后续参数传参

call和apply都是对函数的直接调用,而bind方法返回的仍然是一个函数,因此后面还需要()来进行调用才可以。

call后面的参数直接放入,而apply的第二个参数是一个数组,这就是两者最大的区别。

五、Js原型和原型链

1、javascript原型

JS中每个函数都存在有一个原型对象属性prototype。并且所有函数的默认原型都是Object的实例。

2、javascript原型链

每个继承父函数的子函数的对象都包含一个内部属性_proto_。该属性包含一个指针,指向父函数的prototype。若父函数的原型对象的_proto_属性为再上一层函数。在此过程中就形成了原型链。

3、特点

原型链实现了继承。
大厂前端面试题总结(JS理论篇)_第3张图片
大厂前端面试题总结(JS理论篇)_第4张图片

六、JS实现继承的方法

1,原型链继承 (有两种实现方式)
(1)Son.prototype = Father.prototype
弊端:Son.prototype.constructor 指向Father,需要手动更改为Son ;Son的实例化对象只能继承Father原型中的方法,无法继承Father本身的属性。
(2)Son.prototype = new Father()
弊端:Son.prototype.constructor 指向Father,需要手动更改为Son;Son的实例化对象共享Father自身的引用类型属性。
2,借助构造函数继承
弊端:Son只能继承Father自身的属性,而无法继承Father原型中的方法。
3,组合式继承
将原型链继承与构造函数结合起来
弊端:通过Father.call() 和 new Father() ,父类构造函数Father被调用了两次。
4,原型式继承
newObj继承了obj的属性和方法,但是同样出现了共享父类中引用类型属性的问题。
5,经典继承(Es5中的新语法:存在兼容性问题,需要做浏览器的能力检测)
6,寄生式继承(类似于原型式继承)
newObj继承了obj的属性和方法,但是同样出现了共享父类中引用类型属性的问题。
7,寄生组合式继承(组合继承+寄生继承)
优点:可以多重继承 解决两次调用 解决实例共享引用类型的问题 原型链保持不变

七、JS又那些内置对象

Math对象:Math.abs(x);//用来返回数的绝对值

Date对象:var date = new Date();// 通过new的方式创建一个日期对象;

Array对象:var arr=new Array();

字符串对象:var str=new String();

八、JS操作数组的方法(Array对象属性)

  • join(separator): 将数组的元素组起一个字符串,以 separator 为分隔符,省略的话则用默认用逗号为分隔符,该方法只接收一个参数:即分隔符。
  • push(): 可以接收任意数量的参数,把它们逐个添加到数组末尾,并返回修改后数组的长度。
  • pop():数组末尾移除最后一项,减少数组的length值,然后返回移除的项。
  • shift():删除原数组第一项,并返回删除元素的值;如果数组为空则返回undefined
  • unshift():将参数添加到原数组开头,并返回数组的长度
  • sort():按升序排列数组项——即最小的值位于最前面,最大的值排在最后面
  • reverse():反转数组项的顺序。
    let arr = [3,2,24,1,53,23,32]
    // output: undefined
    arr.sort((a, b) => {
        return a - b
    })
    // output: [1, 2, 3, 23, 24, 32, 53]
    
  • concat():将参数添加到原数组中。这个方法会先创建当前数组一个副本,然后将接收到的参数添加到这个副本的末尾,最后返回新构建的数组。在没有给 concat()方法传递参数的情况下,它只是复制当前数组并返回副本。
  • slice():返回从原数组中指定开始下标到结束下标之间的项组成的新数组。slice()方法可以接受一或两个参数,即要返回项的起始和结束位置。在只有一个参数的情况下, slice()方法返回从该参数指定位置开始到当前数组末尾的所有项。如果有两个参数,该方法返回起始和结束位置之间的项——但不包括结束位置的项。
  • splice():很强大的数组方法,它有很多种用法,可以实现删除、插入和替换。

ES5新增

  • indexOf():接收两个参数:要查找的项和(可选的)表示查找起点位置的索引。其中, 从数组的开头(位置 0)开始向后查找。
  • lastIndexOf():接收两个参数:要查找的项和(可选的)表示查找起点位置的索引。其中, 从数组的末尾开始向前查找。

这两个方法都返回要查找的项在数组中的位置,或者在没找到的情况下返回-1。在比较第一个参数与数组中的每一项时,会使用全等操作符。

  • forEach():对数组进行遍历循环,对数组中的每一项运行给定函数。这个方法没有返回值。参数都是function类型,默认有传参,参数分别为:遍历的数组内容;对应的数组索引,数组本身。
  • map():指映射,对数组中的每一项运行给定函数,返回每次函数调用的结果组成的数组。
  • filter():“过滤”功能,数组中的每一项运行给定函数,返回满足过滤条件组成的数组。
  • every():判断数组中每一项都是否满足条件,只有所有项都满足条件,才会返回true。
  • some():判断数组中是否存在满足条件的项,只要有一项满足条件,就会返回true。
  • reduce():接收一个函数作为累加器,数组中的每个值(从左到右)开始缩减,最终计算为一个值。
    let arr = [1,2,3,4,5]
    let result = arr.reduce((total, curVal) => {
    	return total + curVal
    })
    // result = 15
    

总结

  • 方法pushpopshuiftunshiftsortreversesplice会修改原数组,其他方法会复制一个新数组

九、JS基本数据类型

JS数据类型目前有八种,其中

  • 五种基本数据类型(单类型):StringNumberBooleannullundefined
  • 一种对象数据类型(引用数据类型):object,其类型分为function、Array、Date等
  • 一种ES6提出的永远不相等的类型:Symbol
  • 一种大数据类型(谷歌67版本提出):bigint

十、JS基本数据类型(2021.3.3)

你可能感兴趣的:(面试题,前端,JS,面试题,大厂,事件循环,原型链)