面试题0725----js篇

132 阅读5分钟

数组方法

一、substr和substring的区别

只取一个值时,两个的效果相同,都是截取字符串

substr和substring的区别1.png

substr(startindex,length)

取两个值时,substr取得是length,字符串长度,表示从起始位置开始总共取多少长度的字符串

substring(startindex,endindex)

substring取得是结束位置得索引,表示得是从起始位置到结束位置得索引

substr和substring的区别2.png

二、slice和splice的区别

slice(startindex,endindex)

slice主要是用来截取数组,或者字符串这些的,返回值是被截取的新数组

slice.png

splice(index,h,item)

splice主要是用来做删除的,他也有添加的功能,item就是添加的元素,h就是删除几个index后面的元素,如果值为0则表示不删除元素,如果为空,则表示删除Index后面所有的元素,返回值是被删除的数组

splice.png

总结:

slice:不会改变原数组,主要作用是截取字符串,返回值是新数组

splice:会改变原数组,主要作用是添加或者删除,返回值是被删除的数组

三、数组转树形结构

思路:利用递归遍历的方式,当id和pid相等时,就把pid给入id的子集里面

转数组1.png

如图所示,先设pid:"" 为第一组树形,其次为pid"1"依次类推,结束递归返回

转数组2.png

四、数组去重方法

1、利用index of的方法

数组去重方法1.png

2、利用includes方法

数组去重3.png

3、利用es6的set语法

数组去重3.png

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的过程

  1. 在内存中开辟一个新空间
  2. 让this指向这个新对象
  3. 执行构造函数中的代码,给这个新的对象添加属性和方法
  4. 返回这个新对象

7、js数据类型和数据类型检测

js的数据类型:

基础类型:string、number、boolean、null、undefined、symbol

复杂类型: function 、 array 、object

基础类型的检测:typeof

复杂类型的检测:Object.prototype.tostring()

8、原型链

每个对象都有它的原型,而原型又是一个对象,所以它也有它的原型,就形成了一个链条,成为原型链。

原型链.png