目录
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;}
定时器有几种,有什么区别
两种,分别是setTimeout和setInterval
区别
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()排序
冒泡排序(两层循环,两两交换)
选择排序
首先在未排序序列中找到最小(大)元素,存放到排序序列的起始位置。
再从剩余未排序元素中继续寻找最小(大)元素,然后放到已排序序列的末尾。
重复第二步,直到所有元素均排序完毕。
插入排序
将第一待排序序列第一个元素看做一个有序序列,把第二个元素到最后一个元素当成是未排序序列。
从头到尾依次扫描未排序序列,将扫描到的每个元素插入有序序列的适当位置。(如果待插入的元素与有序序列中的某个元素相等,则将待插入元素插入到相等元素的后面。)