Javascript面试题,整理好咯

中级前端面试题,不低于12k,整理的是js较高频知识点,可能不够完善,大家有兴趣可以留言补充,我会逐步完善,若发现哪里有错,还请多多斧正,哈哈

http和浏览器相关知识点,已分离出,会在下篇整理

 

数据类型

分为基本类型、引用类型。

基本类型包括undefined、null、string、number、boolean、symbol、bigint;

symbol为es6新增,表示独一无二的值;

bigint表示大整数,防止数值较大时丢失精度;

引用类型为object,包含array、function、date。

 

undefined、null的区别

undefined表示未定义、没有值,null表示空对象

 

基本类型、引用类型的区别

内存分为栈内存、堆内存,栈内存先进后出,堆内存先进先出。

基本类型存放在栈内存,引用类型存放在堆内存;

基本类型不可添加属性、方法,而引用类型可以。

 

数据类型检测方法

typeof:使用简单,但存在缺陷,对引用类型除function外,都返回object;

instanceof:检测对象是否属于某个类,返回布尔值,但不能检测基本类型;

constructor:除undefined、null以外,其他对象的__proto__上都有constructor属性;

Object.prototype.toString.call():终极方案。

 

数组常用方法

分为改变原数组、不改变原数组两种。

改变原数组:

push:向末尾添加一个;

pop:删除最后一个;

unshift:向开头添加一个;

shit:删除第一个;

sort:不传参时默认为升序,传参可设置升序、降序;

forEach:遍历数组,修改元素,无返回值;

reverse:将数组翻转,倒置;

splice: 可增,删,修改。

注意:splice(index, length, item),index为开始下标,length为删除个数,item为替换项

只传index,会删除index之后(包含index)的所有元素;

index、length俩参数,会删除掉index之后的length个元素,length为0,则不删除;

index、length、item三个参数,length为0时,会在index之后添加item;length大于0时,会删除length个,并将item替换进去。

不改变原数组:

jion:将元素以字符拼接,返回字符串;

concat:拼接多个数组;

slice:切割数组,slice(start, end),start为开始下标,end为截止下标(不含end);

map:遍历数组,返回新数组;

filter:查找符合条件的元素,返回新数组;

find:查找符合条件的元素,返回该元素;

findIndex:查找元素首次出现的下标值,并返回下标值;

includes:检查数组是否包含某元素,返回布尔值;

some:检测数组是否有元素满足条件,有一个满足则返回true,并终止;

every:检测数组元素是否都满足条件,都满足返回true,否则false;

reduce:遍历数组,并返回一个最终的构建值(比如累加)。

 

数组排序

常见排序有sort排序、冒泡排序、选择排序、快速排序。

sort排序:传参可设置升序、降序,不传参时默认为升序;

冒泡排序:for循环嵌套for循环,两两比较,大的放后面;

选择排序:for循环嵌套for循环,先假设下标为0的是最小值,两两对比,小于最小值,则更新下标,并替换最小值;

快速排序:冒泡排序的改进版,设定分界值,根据分界值把数组分为左右两部分,比分界值小的放左边,大的放右边,再递归,最后合并。

 

数组去重

数组去重常用方法有indexof、filter、for循环、set结构。

indexof:for循环,将下标等于-1的元素push进空数组;

filter:filter的第三个参数self为当前数组,搭配indexof将首次出现的数据筛出来;

for循环嵌套for循环,两两比较,相同则删除;

set结构:es6的new Set()。

 

闭包

闭包是指能访问并操作其他函数内部变量的函数,由于作用域链的关系,形成了闭包。

 

闭包使用场景

使用场景:模块化开发、实现回调函数、事件处理、实现递归、实现函数柯里化等。

模块化开发:封装私有变量、私有方法,避免全局命名冲突和变量污染。

事件处理:在循环或定时器等异步操作中,很常用。

实现函数柯里化:柯里化是一种函数编程技术,将多个参数的函数转换为一系列只接受一个参数的函数。闭包可以很好实现柯里化。

 

闭包优缺点

优点:数据持久化、避免全局变量污染、提高安全性;

缺点:增加内存占用,使用不当会造成内存泄露;过度使用会降低代码可读性,不利于维护。

 

常见内存泄露

闭包(变量被持久化,不会被回收);

全局变量(相当于挂载到window对象上);

未移除的事件监听或定时器。

 

防抖、节流

防抖:事件被触发多次,但只生效最后一次;

节流:一段时间内,事件只被实际触发一次;

常见防抖:输入框;常见节流:滚动、表单提交。

 

this指向

全局上下文:this指向window;

普通函数:this指向它的调用者,没有调用者,则指向window;

箭头函数:没有this,捕获上下文this;

构造函数:this指向自己的实例对象;

事件处理:this指向触发事件的元素本身。

 

apply、call、bind

三者都可以改变this指向。

call和apply很类似,除第一个参数(需绑定到对象的上下文),call接受的是多个参数对象,而apply接受的是一个数组(包含多个参数对象的数组);

bind会创建新的绑定函数,并包装原函数对象,调用绑定函数通常会执行原函数。

注意:bind无法改变构造函数的this指向。

 

深拷贝、浅拷贝

作用于引用类型object、array。

浅拷贝只复制了对象的this,没复制本身,新旧对象共享同一个内存,修改新对象会改变原对象;

深拷贝开辟了独立空间,新旧对象不再共享内存,修改新对象不会改变原对象;

浅拷贝实现方法:Object.assign(只有一层结构,是深拷贝)、concat、slice;

深拷贝实现方法:JSON.parse(JSON.stringify()) 、递归循环

 

JSON.stringify()的缺点

时间对象:序列化和反序列化后,会变成字符串;

正则对象:序列化会变空对象;

函数对象:序列化则会丢失

 

new操作符

创建空对象;设置原型链;绑定this;继承方法和属性(执行构造函数);返回新对象。

 

原型、原型链

原型:对象的prototype属性所指向的原型对象;

原型链:原型对象也有自己的原型对象,向下通过__proto__一层层查找,形成了原型链,原型链终点返回null。

 

原型链的终点为什么是null

原型链上所有节点都是对象,不能是字符串、数字、布尔值等类型;

规范要求原型链必须有限长度。

 

作用域、作用域链

作用域:变量或方法被访问的有效范围;

作用域有三个:全局作用域,块级作用域,函数作用域;

作用域链:函数执行时查找标识,从当前作用域找到外部,一直到全局作用域,一层层向上查找,形成作用域链。

 

函数声明函数表达式

函数声明:是完整语句;在代码执行前创建;未调用也占内存。

函数表达式:是语句的一部分;在代码运行时临时创建;调用完立即释放内存。

 

事件循环

js运行中处理异步任务和事件的机制。

异步任务分为宏任务、微任务两种,先从宏任务队列取出第一个,当执行宏任务碰到微任务时,把微任务放入微任务队列,执行完当前宏任务,再执行微任务,当所有的微任务都执行完,再从宏任务取下一个执行,如此反复,直到所有任务都执行完成。

微任务:常见的Promise.then,$nextTick;

宏任务:除了微任务,其他都是宏任务,比如setTimeout,setInterval。

 

 

事件冒泡、事件委托

事件冒泡:元素接收事件时,会将事件传递给父级,层层传递,直到window;

事件委托:原理为事件冒泡机制;

阻止冒泡事件:click.stop;

阻止默认事件:click.prevent;

事件委托优点:减少事件注册,节省内存;缺点:无需绑定事件的也会被绑定。

 

js盒模型

分为三种:标准盒模型、IE盒模型、CSS3盒模型。

标准盒模型:由W3C规范定义,元素宽高仅为content,不包含其他(border、padding、margin);

IE盒模型:IE浏览器独有,元素宽高为content+padding+border,不含margin;

CSS3盒模型:CSS3引入的新模型,元素宽高为content+padding+border+margin。

获取、设置元素的宽度和高度:  

标准盒模型,使用clientWidth、clientHeight获取元素的内容区宽高;

IE盒模型, 使用offsetWidth、offsetHeight获取元素的实际宽高;

CSS3盒模型,使用getBoundingClientRect()获取元素的实际宽高。

 

== 和 ===

两者都可判断两个值是否相等。

==没有===严谨;

==在比较不同类型的值时,会先转成同类型(隐式强制转换)再去比较,===则不会。

 

javascript继承

分为原型链继承、构造函数继承、组合继承、Object.create()、class继承。

原型链继承:最基本的继承方式,每个对象都有一个原型对象,通过原型链将属性、方法传递,子构造函数的原型对象指向父级实例,实现继承。

构造函数继承:子构造函数使用call或apply方法,改变this指向,将父构造函数的上下文设为子对象的上下文,实现继承。

组合继承:结合了原型链继承和构造函数继承。

Object.create():将现有对象属性挂载到新建对象的原型上,实现继承。

class继承:es6引入的类概念,通过class关键字和extends关键字,实现类的继承。

 

javascript如何处理异常

try...catch...finally:try里放入可能出现异常的代码,catch捕获异常,finally释放资源(无论是否异常,最后都会执行)。

throw关键字:手动抛出异常。

promise中异常:通过catch捕获。

 

javascript高阶函数

高阶函数需满足特性(接受一个或多个参数、返回一个函数)中至少一个;

优点:使代码更加简洁、易维护;

常见高阶函数:map、filer、find、findexIndex、forEach、some、every、sort等等。

 

函数柯里化

柯里化是一种函数的转换技术,将函数f(a,b,c)转换成f(a)(b)(c)。

优点:函数职责单一、可复用、

通过箭头函数实现简单例子:

// const sum = x => y => z => x + y + z;

// const total = sum(1)(2)(3);

// console.log(total ); // 输出6

 

defer、async

两者都是异步执行方案,解决js自上而下同步解析时,可能带来的阻塞。

defer会保证执行顺序,async不能保证。

 

Dom操作

创建节点:creatElement方法(创建节点)、appendChild方法(末尾插入节点)、cloneNode方法(克隆节点)

删除节点:removeChild方法(删除某个子节点)

获取节点:getElementById、getElementsByTagName、getElementsByClassName、getElementsByName属性(通过name属性获取节点)

查找节点:parentNode属性(查父节点)、childNodes和children属性(查子节点)

 

CommonJS

是一种模块化规范,将代码分割成一个个模块,每个模块拥有独立作用域。

核心功能:导入(require),导出(exports)。

 

 

posted @ 2020-04-27 10:33  一杯龙井解千愁  阅读(798)  评论(2)    收藏  举报