数组方法
一、substr和substring的区别
只取一个值时,两个的效果相同,都是截取字符串
substr(startindex,length)
取两个值时,substr取得是length,字符串长度,表示从起始位置开始总共取多少长度的字符串
substring(startindex,endindex)
substring取得是结束位置得索引,表示得是从起始位置到结束位置得索引
二、slice和splice的区别
slice(startindex,endindex)
slice主要是用来截取数组,或者字符串这些的,返回值是被截取的新数组
splice(index,h,item)
splice主要是用来做删除的,他也有添加的功能,item就是添加的元素,h就是删除几个index后面的元素,如果值为0则表示不删除元素,如果为空,则表示删除Index后面所有的元素,返回值是被删除的数组
总结:
slice:不会改变原数组,主要作用是截取字符串,返回值是新数组
splice:会改变原数组,主要作用是添加或者删除,返回值是被删除的数组
三、数组转树形结构
思路:利用递归遍历的方式,当id和pid相等时,就把pid给入id的子集里面
如图所示,先设pid:"" 为第一组树形,其次为pid"1"依次类推,结束递归返回
四、数组去重方法
1、利用index of的方法
2、利用includes方法
3、利用es6的set语法
js语法面试题
一、深拷贝和浅拷贝
什么是浅拷贝
浅拷贝是指,一个新的对象对原始对象的属性值进行精确地拷贝,如果拷贝的是基本数据类型,拷贝的就是基本数据类型的值;如果拷贝的是引用数据类型,拷贝的就是内存地址。如果其中一个对象的引用内存地址发生改变,另一个对象也会发生变化。
浅拷贝的方法
1、Object.assign()
let target = {a: 1}; let object2 = {b: {d : 2}}; let object3 = {c: 3};
Object.assign(target, object2, object3);
console.log(target); // {a: 1, b: {d : 2}, c: 3}
2、扩展运算符
let obj1 = {a:1,b:{c:1}}
let obj2 = {...obj1};
obj1.a = 2;
console.log(obj1); //{a:2,b:{c:1}}
console.log(obj2); //{a:1,b:{c:1}}
obj1.b.c = 2;
console.log(obj1); //{a:2,b:{c:2}}
console.log(obj2); //{a:1,b:{c:2}}
什么是深拷贝
深拷贝是指,对于简单数据类型直接拷贝他的值,对于引用数据类型,在堆内存中开辟一块内存用于存放复制的对象,并把原有的对象类型数据拷贝过来,这两个对象相互独立,属于两个不同的内存地址,修改其中一个,另一个不会发生改变。
1、JSON.stringify()
let item1 = {
a: 3,
b: {
c: 3
}
};
let item2 = JSON.parse(JSON.stringify(obj1));
obj1.a = 2;
obj1.b.c = 2;
console.log(item1); // {a: 2, b: {c: 2}}
console.log(item2); // {a: 3, b: {c: 3}}
缺点:
拷贝的对象中如果有函数,undefined,symbol,当使用过JSON.stringify()进行处理之后,都会消失。
2、递归拷贝(最稳定的写法)
export const setKeys = (oldData, newData) => {
if (oldData instanceof Array) {
oldData.forEach((item, index) => {
newData[index] = {}
setKeys(item, newData[index])
})
} else if (oldData instanceof Object) {
for (const key in oldData) {
if (key === 'label') {
newData.text = oldData[key]
} else if (key === 'children') {
newData[key] = []
setKeys(oldData[key], newData[key])
} else {
newData[key] = oldData[key]
}
}
} else {
newData = oldData
}
}
二、promise的3种状态
Promise 会有三种状态
- Pending 等待
- Resolved 完成
- Rejected 失败
状态只能由 Pending --> Resolved 或者 Pending --> Rejected,且一但发生改变便不可二次修改;
Promise 中使用 resolve 和 reject 两个函数来更改状态;
then 方法内部做但事情就是状态判断
- 如果状态是成功,调用成功回调函数
- 如果状态是失败,调用失败回调函数
三、let const var区别
1、let、const 没有变量提升 var 有预解析变量提升
2、let、const 具有块级作用域
3、let、const 具有暂时性死区,在变量被声明完成前,不能被使用的
四、事件循环—宏任务和微任务
定义:
异步任务分为两种、一种是宏任务、一种是微任务
异步执行的任务和js处于同一个进程和js相关的 属于微任务
而在一个新的进程做的事情和js无关 属于宏任务
执行顺序:
同步代码->微任务->宏任务->微任务
常见的微任务: promise object.observer
常见的宏任务u: setTimeout setInterval ajax Dom事件等
五、防抖节流
节流:
几秒内只运行一次,若在几秒内重复触发,只有一次生效
防抖:
几秒后在执行该事件,若在几秒内被重复触发,则重新计时
常用的节流操作:
手机获取验证码,60s内点击一次,只有一次生效,等60s过后,才能获取第二次验证码
常用的防抖操作:
搜索框关键字搜索、1s后进行关键字搜索、减少ajax的请求交互,节省运行资源
6、new的过程
- 在内存中开辟一个新空间
- 让this指向这个新对象
- 执行构造函数中的代码,给这个新的对象添加属性和方法
- 返回这个新对象
7、js数据类型和数据类型检测
js的数据类型:
基础类型:string、number、boolean、null、undefined、symbol
复杂类型: function 、 array 、object
基础类型的检测:typeof
复杂类型的检测:Object.prototype.tostring()
8、原型链
每个对象都有它的原型,而原型又是一个对象,所以它也有它的原型,就形成了一个链条,成为原型链。