1200字范文,内容丰富有趣,写作的好帮手!
1200字范文 > JS + ES6 高频面试题合集

JS + ES6 高频面试题合集

时间:2022-02-06 15:59:09

相关推荐

JS + ES6 高频面试题合集

目录

js数据类型有哪些

基本数据类型

引用数据类型

内置对象有哪些

数组方法有哪些

数组去重几种方式

1--双重for循环

2--indexOf()方法

3--splice()方法

4--filter()方法

5--利用对象属性不能重复的特点

6--利用Set结构成员不能重复的特点

7--利用Map结构成员不能重复的特点

数组深拷贝几种方式

1--for循环

2--slice方法

3--concat方法

4--扩展运算符

对象深拷贝几种方式

1--for...in...循环

2--利用JSON,先转JSON字符串在转JSON对象

3--扩展运算符

4--Es6中的Object.assign方法

定时器有几种,有什么区别

区别

说下对Promise的理解

一、Promise是什么?

二、Promise是为解决什么问题而产生的?

三、Promise的两个特点

四、Promise的三个缺点

五、Promise的用法

说下对模块导入导出的理解

箭头函数和普通函数的区别

Js实现约瑟夫环问题(m个人留1个或者留n-1个)

数组方法

递归方法

数组排序的几种写法

数组排序方法sort()排序

冒泡排序(两层循环,两两交换)

选择排序

插入排序

js数据类型有哪些

基本数据类型

Number 数字类型

String 字符串类型

Boolean布尔类型

undefined未定义

null 空型

Symbol 唯一值

引用数据类型

数组

函数

对象

Set

Map

内置对象有哪些

Math:数学对象,数学和函数相关的

Date:日期对象,处理日期和时间

Array:数组对象

String:字符串对象

数组方法有哪些

1--unshift------添加元素,在数组最前边添加,返回数组的长度

2--shift------删除元素,在数组最前边删除,返回删除的元素

3--reverse------翻转数组,返回一个新数组,会改变原来的数组

4--sort------排序,默认从大到小排序,改变原来的数组

5--concat------拼接,如果参数是数组,则拼接数组;如果参数是非数组,在末尾添加元素。返回新数组,原数组不变

6--slice(start,end)------截取,从索引start开始截取,到end结束,包括start不包括end,原数组不变

7--splice(start,length)------截取,从索引start截取length个元素,原数组改变

8--indexOf------查询某元素的索引,从前往后查找第一次出现的索引,没有返回-1

9--lastIndexOf------查询某元素的索引,从后往前查找第一次出现的索引,没有返回-1

10--join------转化,通过指定分隔符连接数组所有元素,返回字符串,默认用逗号分隔

11--forEach------遍历数组,没有返回值

12--some-----判断元素是否满足条件,有一个满足就返回true,都不满足返回false

13--every-----判断元素是否满足条件,都满足就返回true,有一个不满足返回false

14--map-----用于数学计算,返回数组

15--filter------过滤元素,过滤出符合条件的元素,返回数组

数组去重几种方式

1--双重for循环

var arrOld = [2, 3, 5, 4, 3, 2, 6, 8, 5, 4, 6, 2];var arrNew = [];var flag = true;for (var i = 0; i < arrOld.length; i++) {flag = true;for (var j = 0; j < arrNew.length; j++) {if (arrNew[j] == arrOld[i]) {flag = false;}}if (flag) {arrNew.push(arrOld[i]);}}console.log(arrNew);

2--indexOf()方法

function unique(arrOld) {var arrNew = [];for (var i = 0; i < arrOld.length; i++) {if (arrNew.indexOf(arrOld[i]) === -1) {arrNew.push(arrOld[i])}}return arrNew;}

3--splice()方法

4--filter()方法

function unique(arrOld) {return arrOld.filter(function(item, index, arrOld) {return arrOld.indexOf(item,0) === index;});}

5--includes()方法

function unique(arr) {if (!Array.isArray(arr)) {console.log('type error!')return}var array =[];for(var i = 0; i < arr.length; i++) {if( !array.includes( arr[i]) ) {array.push(arr[i]);}}return array}

6--利用对象属性不能重复的特点

var arrOld = [2, 3, 5, 4, 3, 2, 6, 8, 5, 4, 6, 2];var arrNew = [];var obj = {};for (var i = 0; i < arrOld.length; i++) {obj[arrOld[i]] = 1;}for (x in obj) {arrNew.push(Number(x));}console.log(arrNew);

7--利用Set结构成员不能重复的特点

function unique (arr) {return Array.from(new Set(arr))}

8--利用Map结构成员不能重复的特点

9--拓展运算符 + Set

[...new Set(arr)]

数组深拷贝几种方式

for循环

var arr1 = [1, 2, 3];var arr2 = [];for (var i = 0; i < arr1.length; i++) {arr2.push(arr1[i]);}arr1[0] = 4;console.log(arr1); //4, 2, 3console.log(arr2); //1, 2, 3

slice方法

var arr1 = [1, 2, 3];var arr2 = arr1.slice(0);arr1[0] = 4;console.log(arr1); //4, 2, 3console.log(arr2); //1, 2, 3

concat方法

var arr1 = [1, 2, 3];var arr2 = arr1.concat();arr1[0] = 4;console.log(arr1); //4, 2, 3console.log(arr2); //1, 2, 3

扩展运算符

var arr1 = [1, 2, 3];var [...arr2] = arr1;arr1[0] = 4;console.log(arr1); //4, 2, 3console.log(arr2); //1, 2, 3

对象深拷贝几种方式

for...in...循环

使用JSON暴力转换

通过JSON.stringify() 和 JSON.parse() 将对象转为字符串之后在转为对象。

var obj = {name:'123'};var obj2 = JSON.parse(JSON.stringify(obj))

这种简单粗暴的方式有局限性,当值为undefined、function、symbol会在转换过程中被忽略。

使用解构赋值

var obj = {name:'123',age:13};var obj2 = {...obj}

只能深度拷贝对象的第一层,如果对象中的属性也是对象的话,没有办法进行深度拷贝的。

使用对象的合并

利用Object.assign(), 第一个参数必须是空对象

var obj = {name:'123',age:13};var obj2 = Object.assign({},obj1);

只能深度拷贝对象的第一层,如果对象中的属性也是对象的话,没有办法进行深度拷贝的。

利用循环和递归的方式

function deepClone(obj, newObj) {var newObj = newObj || {};for (let key in obj) {if (typeof obj[key] == 'object') {newObj[key] = (obj[key].constructor === Array) ? [] : {}deepClone(obj[key], newObj[key]);} else {newObj[key] = obj[key]}}return newObj;}

定时器有几种,有什么区别

两种,分别是setTimeoutsetInterval

区别

1--setTimeout隔一段时间之后执行,只执行一次; setInterval每个一段时间之后执行一次,执行多次

2--setTimeout用clearTimeout清;除setInterval用clearInterval清除

说下对Promise的理解

一、Promise是什么?

Promise是最早由社区提出和实现的一种解决异步编程的方案,比其他传统的解决方案(回调函数和事件)更合理和更强大。

ES6 将其写进了语言标准,统一了用法,原生提供了Promise对象。

ES6 规定,Promise对象是一个构造函数,用来生成Promise实例。

二、Promise是为解决什么问题而产生的?

promise是为解决异步处理回调金字塔问题而产生的

三、Promise的两个特点

1、Promise对象的状态不受外界影响

1)pending 初始状态

2)fulfilled 成功状态

3)rejected 失败状态

Promise 有以上三种状态,只有异步操作的结果可以决定当前是哪一种状态,其他任何操作都无法改变这个状态

2、Promise的状态一旦改变,就不会再变,任何时候都可以得到这个结果,状态不可以逆,只能由 pending变成fulfilled或者由pending变成rejected

四、Promise的三个缺点

1)无法取消Promise,一旦新建它就会立即执行,无法中途取消

2)如果不设置回调函数,Promise内部抛出的错误,不会反映到外部

3)当处于pending状态时,无法得知目前进展到哪一个阶段,是刚刚开始还是即将完成

五、Promise的用法

1、Promise构造函数接受一个函数作为参数,该函数的两个参数分别是resolve和reject。它们是两个函数,由 JavaScript 引擎提供,不用自己部署。

2、resolve函数的作用是,将Promise对象的状态从“未完成”变为“成功”(即从 pending 变为 resolved),在异步操作成功时调用,并将异步操作的结果,作为参数传递出去;reject函数的作用是,将Promise对象的状态从“未完成”变为“失败”(即从 pending 变为 rejected),在异步操作失败时调用,并将异步操作报出的错误,作为参数传递出去。

3、Promise实例生成以后,可以用then方法分别指定resolved状态和rejected状态的回调函数。

then方法可以接受两个回调函数作为参数。第一个回调函数是Promise对象的状态变为resolved时调用,第二个回调函数是Promise对象的状态变为rejected时调用。其中,第二个函数是可选的,不一定要提供。这两个函数都接受Promise对象传出的值作为参数

六、Promise.race()方法

Promise.all( )方法:接受一个数组作为参数,数组的元素是Promise实例对象,当参数中的实例对象的状态都为fulfilled时,Promise.all( )才会有返回。

//创建实例pro1let pro1 = new Promise(function(resolve){setTimeout(function () {resolve('实例1操作成功');},5000);});//创建实例pro2let pro2 = new Promise(function(resolve){setTimeout(function () {resolve('实例2操作成功');},1000);});Promise.all([pro1,pro2]).then(function(result){console.log(result);});//打印结果:["实例1操作成功", "实例2操作成功"]

Promise.all获得的成功结果的数组里面的数据顺序和Promise.all接收到的数组顺序是一致的,即p1的结果在前,即便p1的结果获取的比p2要晚。这带来了一个绝大的好处:在前端开发请求数据的过程中,偶尔会遇到发送多个请求并根据请求顺序获取和使用数据的场景,使用Promise.all毫无疑问可以解决这个问题。

我们执行某个操作,这个操作需要得到需要多个接口请求回来的数据来支持,但是这些接口请求之前互不依赖,不需要层层嵌套。这种情况下就适合使用Promise.all( )方法,因为它会得到所有接口都请求成功了,才会进行操作。

七、Promise.all()方法

Promise.race()方法:它的参数要求跟Promise.all( )方法一样,不同的是,它参数中的promise实例,只要有一个状态发生变化(不管是成功fulfilled还是异常rejected),它就会有返回,其他实例中再发生变化,它也不管了

//初始化实例pro1let pro1 = new Promise(function(resolve){setTimeout(function () {resolve('实例1操作成功');},4000);});//初始化实例pro2let pro2 = new Promise(function(resolve,reject){setTimeout(function () {reject('实例2操作失败');},2000);});Promise.race([pro2,pro1]).then(function(result){console.log(result);}).catch(function(error){console.log(error);});//打印结果:实例2操作失败

由于pro2实例中2000毫秒之后就执行reject方法,早于实例pro1的4000毫秒,所以最后输出的是:实例2操作失败。

说下对模块导入导出的理解

模块化的初衷

现在的web系统越来越庞大、复杂,需要团队分工,多人协作,大型系统的javascript文件经常存在复杂的依赖关系,后期的维护成本会越来越高。

JavaScript模块化正式为了解决这一需求而诞生。

1--导出: 选择性地给其他模块暴露(提供)自己的属性和方法,供其他模块使用。

2--导入: 可以根据需要,引入其他模块的提供的属性或者方法,供自己模块使用。

3--批量导出: export {name,age} 批量导入import {name,age} from “url”;

4--整体导入: import * as obj from “url” 变量作为obj的属性

5--重命名导出入的变量:import {旧名字 as 新名字} from “url”;

6--默认导出:export default 变量 (导出没有名字的变量,只能有一个)

7--在导入时import 自定义名 from ”url”自定义名字不用大括号包住

8--注意

1.声明的变量,对外都是只读的。但是,如果模块B导出的是对象类型的值,就可修改。

2.导入不存在的变量,会报错。

箭头函数和普通函数的区别

1--箭头函数更简洁,不需要function,需要在()后加=> 如果只有一个参数可以省略(),如果函数只有一个return语句,可以省略return 和 {}

2--箭头函数都是匿名函数,普通函数有匿名函数和具名函数

3--箭头函数没有arguments,caller,callee;普通函数调用后会有argument对象

4--箭头函数不能作为构造函数,不能使用new;普通函数可以作为构造函数创建对象实例

5—箭头函数没有原型prototype属性

6--箭头函数的this永远指向父作用域,箭头函数通过call和apply调用,不会改变this指向,只会传入参数。普通函数的this指向可以通过call和apply改变。

7--箭头函数不能作为Generator函数,不能使用yield关键字

8--箭头函数返回对象时,要加一个小括号

9--箭头函数在ES6 class中声明的方法为实例方法,不是原型方法

Js实现约瑟夫环问题(m个人留1个或者留n-1个)

数组方法

function countOff(num, m) {let players = [];for (let i = 1; i <= num; i++) {players.push(i);}let flag = 0;while (players.length > 1) {// 剩下一人,结束条件let outPlayerNum = 0,len = players.length;for (let i = 0; i < len; i++) {flag++;if (flag === m) {flag = 0;console.log("出局:" + players[i - outPlayerNum]);players.splice(i - outPlayerNum, 1);outPlayerNum++;}}}console.log("剩下:" + players[0]);}

递归方法

function countOff(N, M) {if (N < 1 || M < 1) {return;}let source = [];for (let i = 1; i <= N; i++) {source.push(i);}// const source = Array(...Array(N)).map((_, i) => i + 1);let index = 0;while (source.length > 1) {// 剩下一人,结束条件index = (index + M - 1) % source.length;console.log("出局:" + source[index]);source.splice(index, 1);}console.log("剩下:" + source[0]);}

数组排序的几种写法

数组排序方法sort()排序

冒泡排序(两层循环,两两交换)

选择排序

首先在未排序序列中找到最小(大)元素,存放到排序序列的起始位置。

再从剩余未排序元素中继续寻找最小(大)元素,然后放到已排序序列的末尾。

重复第二步,直到所有元素均排序完毕。

插入排序

将第一待排序序列第一个元素看做一个有序序列,把第二个元素到最后一个元素当成是未排序序列。

从头到尾依次扫描未排序序列,将扫描到的每个元素插入有序序列的适当位置。(如果待插入的元素与有序序列中的某个元素相等,则将待插入元素插入到相等元素的后面。)

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。