Skip to main content
 Web开发网 » 数据库教程

啃透这份JS高频面试习题后,还怕跟面试官对线吗?

2021年10月11日11270百度已收录

Hello,今天给各位童鞋们分享的是JS面试习题,赶紧拿出小本子记下来吧

啃透这份JS高频面试习题后,还怕跟面试官对线吗?  jQuery面试 第1张

1.关于闭包什么是闭包?

闭包是有权限访问其它函数作用域内的变量的一个函数。

在js中,变量分为全局变量和局部变量,局部变量的作用域属于函数作用域,在函数执行完以后作用域就会被销毁,内存也会被回收,但是由于闭包是建立在函数内部的子函数,由于其可访问上级作用域的原因,即使上级函数执行完,作用域也不会被销毁,此时的子函数——也就是闭包,便拥有了访问上级作用域中变量的权限,即使上级函数执行完以后作用域内的值也不会被销毁。

闭包有三个特性:

1.函数嵌套函数

2.函数内部可以引用外部的参数和变量

3.参数和变量不会被垃圾回收机制回收

闭包解决了什么?

本质上,闭包就是将函数内部和函数外部连接起来的一座桥梁。由于闭包可以缓存上级作用域,这样函数外部就可以访问到函数内部的变量。

闭包的应用场景

ajax请求成功的回调 一个事件绑定的回调方法 setTimeout的延时回调 一个函数内部返回另一个匿名函数

闭包的优缺点

优点: 让代码更加规范、简洁

缺点: 使用闭包过多,内存消耗大,造成内存的泄露

2.原型和原型链(1) 所有的引用类型都有一个_proto_(隐式原型)属性,属性值是一个普通的对象

(2) 所有的函数除了有_proto_属性,还都有一个prototype(显式原型)属性,属性值是一个普通的对象

(3) 所有引用类型的_proto_属性指向它构造函数的prototype

当一个对象调用自身不存在的属性/方法时,会先去它的_proto_上查找,也就是它的构造函数的prototype;如果没有找到,就会去该构造函数的prototype的_proto_指向的上一级函数的prototype中查找,再往上会指向对象的prototype,最后指向null。这样一层一层向上查找的关系会形成一个链式结构,称为原型链。

3.ES5继承和ES6继承ES5: 组合式继承,先创建子类的实例对象,然后再将父类的方法通过call方法添加到this上,通过原型和构造函数的机制来实现

示例:

啃透这份JS高频面试习题后,还怕跟面试官对线吗?  jQuery面试 第2张

ES6: 先创建父类的实例对象this(所以必须先调用父类的super()方法,然后再用子类的构造函数修改this),通过class关键字定义类,类之间通过extends关键字实现继承,子类必须在constructor方法中调用super方法。因为子类没有自己的this对象,而是继承了父类的this对象,然后对其加工,如果不调用super方法,子类得不到this对象。

示例:

啃透这份JS高频面试习题后,还怕跟面试官对线吗?  jQuery面试 第3张

4.原生AJAX请求步骤五步使用法:

(1) 创建XML请求:

啃透这份JS高频面试习题后,还怕跟面试官对线吗?  jQuery面试 第4张

POST请求:

啃透这份JS高频面试习题后,还怕跟面试官对线吗?  jQuery面试 第5张

5.关于事件委托什么是事件委托

事件委托也叫事件代理,就是利用事件冒泡,只指定一个事件处理程序,就可以管理某一类型的所有事件。

事件委托的作用

(1) 提高性能:每一个函数都会占用内存空间,只需添加一个时间处理程序代理所有事件,所占用的内存空间更少;

(2) 动态监听:使用事件委托可以自动绑定动态添加的元素,即新增的节点不需要主动添加也可以具有和其它元素一样的事件。

实现方式 我们先来看看,如果不用事件委托,需要绑定多个相同事件的时候是如何实现的:

啃透这份JS高频面试习题后,还怕跟面试官对线吗?  jQuery面试 第6张

不使用事件委托,那就要遍历每一个li元素,给每个li元素绑定一个点击事件,这样的做法非常耗费内存,如果有100个、1000个li元素,那对性能的影响是非常大的。

那么使用事件委托是怎么实现的呢?

啃透这份JS高频面试习题后,还怕跟面试官对线吗?  jQuery面试 第7张

这样一来,通过事件委托,只需要在li元素的父元素ul上绑定一个点击事件,通过事件冒泡的机制,就可以实现li的点击效果。并且通过js动态添加li元素,也能绑定点击事件。

6.null不是一个对象,但为什么typeof null === object原理是这样的,不同的对象在底层都会表示为二进制,在js中如果二进制的前三位都为0,就会被判断为object类型,null的二进制全为0,自然前三位也是0,所以typeof null === objcet。

7.关于浅拷贝和深拷贝浅拷贝: 只复制指向某个对象的指针,而不复制对象本身,新旧对象还是共享同一块内存

实现:

方法一:直接用=赋值

let obj1 = {a: 1}

let obj2 = obj1

方法二:Object.assign

let obj1 = {a: 1}

let obj2 = {}

Object.assign(obj2, obj1)

方法三:for in循环只遍历第一层

啃透这份JS高频面试习题后,还怕跟面试官对线吗?  jQuery面试 第8张

深拷贝:

方法一:用 JSON.stringify 把对象转换成字符串,再用 JSON.parse 把字符串转换成新的对象

啃透这份JS高频面试习题后,还怕跟面试官对线吗?  jQuery面试 第9张

方法二:采用递归去拷贝所有层级属性

啃透这份JS高频面试习题后,还怕跟面试官对线吗?  jQuery面试 第10张

方法三:lodash函数库实现深拷贝

啃透这份JS高频面试习题后,还怕跟面试官对线吗?  jQuery面试 第11张

方法四:通过jQuery的extend方法实现深拷贝

let array = [1,2,3,4]

let newArray = $.extend(true,[],array) // true为深拷贝,false为浅拷贝

方法五:用slice实现对数组的深拷贝

啃透这份JS高频面试习题后,还怕跟面试官对线吗?  jQuery面试 第12张

方法六:使用扩展运算符实现深拷贝

let obj1 = {brand: "BMW", price: "380000", length: "5米"}

let obj2 = { ...car, price: "500000"}

8.谈谈js的垃圾回收机制js拥有自动的垃圾回收机制,当一个值在内存中失去引用时,垃圾回收机制会根据特殊的算法找到它,并将其回收,释放内存。

标记清除法(常用)

(1) 标记阶段:垃圾回收器会从根对象开始遍历。每一个可以从根对象访问到的对象都会被添加一个标识,于是这个对象就被标识为可到达对象

(2) 清除阶段:垃圾回收器会对堆内存从头到尾进行线性遍历,如果发现有对象没有被标识为可到达对象,那么就将此对象占用的内存回收,并且将原来标记为可到达对象的标识清除,以便进行下一次垃圾回收操作;

优点:实现简单

缺点:可能会造成大量的内存碎片

引用计数清除法

(1) 引用计数的含义就是跟踪记录每个值被引用的次数,当声明了一个变量并将一个引用类型赋值给该变量时,这个值的引用次数就是1。相反,如果包含对这个值引用的变量又取得了另外一个值,这个值的引用次数就减1。

(2) 当这个引用次数变成0时,则说明没有办法再访问这个值了,就可以将其所占的内存空间给回收。这样,垃圾收集器下次再运行时,就会释放那些引用次数为0的值所占的内存。

优点: (1) 可即刻回收垃圾

缺点: (1) 计数器值的增减处理繁重

(2) 实现繁琐复杂

(3) 循环引用无法回收

9.如何阻止事件冒泡和默认事件标准的DOM对象中可以使用事件对象的stopPropagation()方法来阻止事件冒泡,但在IE8以下中的事件对象通过设置事件对象的cancelBubble属性为true来阻止冒泡默认事件通过事件对象的preventDefault()方法来阻止,而IE通过设置事件对象的returnValue属性为false来阻止默认事件10.函数防抖和函数节流函数防抖(debounce): 当调用函数n秒后,才会执行该动作,若在这n秒内又调用该函数则取消前一次并重新计算执行时间(频繁触发的情况下,只有足够的空闲时间,才执行代码一次)

啃透这份JS高频面试习题后,还怕跟面试官对线吗?  jQuery面试 第13张

函数节流(throttle): 函数节流的基本思想是函数预先设定一个执行周期,当调用动作的时刻大于等于执行周期则执行该动作,然后进入下一个新周期(一定时间内js方法只跑一次。比如人的眨眼睛,就是一定时间内眨一次)

啃透这份JS高频面试习题后,还怕跟面试官对线吗?  jQuery面试 第14张

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

12.箭头函数和普通函数的区别箭头函数:

(1)在使用 => 定义函数的时候,this的指向是定义时所在的对象,而不是使用时所在的对象,bind()、call()、apply()均无法改变指向

(2) 不能用做构造函数,也就是说不能使用new命令,否则就会抛出一个错误

(3) 不能使用arguments对象,但是可以使用…rest参数

(4) 不能使用yield命令

(5) 没有原型属性

普通函数:

(1) this总是代表它的直接调用者

(2) 在默认情况下,没找到直接调用者,this指向window

(3) 在严格模式下,没有直接调用者的函数中的this是undefined

(4) 使用call,apply,bind绑定,this指的是绑定的对象

13.call()、apply()、bind()的区别call()、apply()、bind()是用来改变this的指向的

call(): Function.call(obj, param1,param2,param3) 接收到的是param1,param2,param3三个参数

apply(): Function.apply(obj, [param1,param2,param3]) 接收到的是param1,param2,param3三个参数

call和apply的区别是参数一个不用[],一个要用[]

bind(): const newFn = Funtion.bind(obj, param1,param2) 返回值是一个函数,需要()来调用 newFn(param3,param4) 接收到的是param1,param2,param3,param4四个参数

14.进程和线程的区别进程(process): 是cpu资源分配的最小单位(是能拥有资源和独立运行的最小单位),是并发执行的程序在执行过程中分配和管理资源的基本单位,是一个动态概念。

线程(thread): 是cpu调度的最小单位(是建立在进程基础上的一次程序运行单位),是进程内可调度的实体,比进程更小的独立运行的基本单位。

一个进程有一个或多个线程,线程之间共同完成进程分配下来的任务,打个比方:● 假如进程是一个工厂,工厂有它的独立的资源 ● 工厂之间相互独立 ● 线程是工厂中的工人,多个工人协作完成任务 ● 工厂内有一个或多个工人 ● 工人之间共享空间

再完善完善概念:

● 工厂的资源 -> 系统分配的内存(独立的一块内存)

● 工厂之间的相互独立 -> 进程之间相互独立

● 多个工人协作完成任务 -> 多个线程在进程中协作完成任务

● 工厂内有一个或多个工人 -> 一个进程由一个或多个线程组成

● 工人之间共享空间 -> 同一进程下的各个线程之间共享程序的内存空间(包括代码段、数据集、堆等)

15.ES6的新特性ES6的特性

(1) 类(class) 对熟悉Java、C、C++等语言的开发者来说,class一点都不陌生。ES6引入了class(类),让JS的面向对象编程变得更加简单和易于理解。

(2) 模块化(Module) ES5不支持原生的模块化,在ES6中模块作为重要的组成部分被添加进来。模块的功能主要由export和import组成。每一个模块都有自己单独的作用域,模块之间的相互调用关系是通过 export 来规定模块对外暴露的接口,通过import来引用其它模块提供的接口。同时还为模块创造了命名空间,防止函数的命名冲突。

导出(export) ES6运行在一个模块中使用export来导出多个变量或函数

啃透这份JS高频面试习题后,还怕跟面试官对线吗?  jQuery面试 第15张

导入(import) 定义好模块的输出以后就可以在另外一个模块通过import引用。

import{myModule} from 'myModule'

import{a,b} from 'test'

(3) 箭头(Arrow) 函数 这是ES6中最令人激动的特性之一。=>不只是关键字function的简写,它还带来了其它好处。箭头函数与包围它的代码共享同一个this,能很好的解决this的指向问题。

(4) 函数参数默认值 ES6 支持在定义函数的时候为其设置默认值,当函数的参数为布尔值false时,可以规避一些问题

啃透这份JS高频面试习题后,还怕跟面试官对线吗?  jQuery面试 第16张

(5) 模板字符串

啃透这份JS高频面试习题后,还怕跟面试官对线吗?  jQuery面试 第17张

(6) 解构赋值 通过解构赋值可以方便的交换两个变量的值:

啃透这份JS高频面试习题后,还怕跟面试官对线吗?  jQuery面试 第18张

获取对象中的值:

啃透这份JS高频面试习题后,还怕跟面试官对线吗?  jQuery面试 第19张

(7) 延展操作符(Spread operator)和剩余运算符(rest operator) 当三个点(…)在等号右边,或者放在实参上,是 spread运算符

啃透这份JS高频面试习题后,还怕跟面试官对线吗?  jQuery面试 第20张

当三个点(…)在等号左边,或者放在形参上,是 rest 运算符

啃透这份JS高频面试习题后,还怕跟面试官对线吗?  jQuery面试 第21张

(8) 对象属性简写 在ES6中允许我们在设置一个对象的属性的时候不指定属性名不使用ES6:

啃透这份JS高频面试习题后,还怕跟面试官对线吗?  jQuery面试 第22张

使用ES6:

啃透这份JS高频面试习题后,还怕跟面试官对线吗?  jQuery面试 第23张

(9) Promise Promise 是异步编程的一种解决方案,比传统的解决方案callback更加的优雅。它最早由社区提出和实现的,ES6 将其写进了语言标准,统一了用法,原生提供了Promise对象。

不使用ES6

啃透这份JS高频面试习题后,还怕跟面试官对线吗?  jQuery面试 第24张

使用ES6

啃透这份JS高频面试习题后,还怕跟面试官对线吗?  jQuery面试 第25张

(10) 支持let与const 在之前JS是没有块级作用域的,const与let填补了这方面的空白,const与let都是块级作用域。

let和var的区别:

● let没有变量提升,存在暂时性死区,必须等let声明完以后,变量才能使用

● let变量不能重复声明

● let声明的变量只在let代码块有效

16.new关键字做了什么?

使用new操作符调用构造函数实际上会经历以下4个步骤:

(1) 创建一个新对象

(2) 将构造函数的作用域赋给新对象(因此this就指向了这个新对象)

(3) 执行构造函数中的代码(为这个新对象添加属性、方法)

(4) 返回新对象

啃透这份JS高频面试习题后,还怕跟面试官对线吗?  jQuery面试 第26张

好啦,今天的文章就到这里了,希望能够帮助到屏幕前迷茫的你们

评论列表暂无评论
发表评论
微信