近期面试的问题总结

55 阅读2分钟

js篇

1、浅拷贝与深拷贝的区别? 常用的手段分别有哪些?

对象的引用是对存储这个对象内存地址的一种引用,也就是当你赋值A对象 = B对象后,假如更改A对象某一个属性的值, 那么B对象中的这个属性也会随着更改。这就是浅拷贝带来的问题。 深拷贝是新对象的内存地址重新指向了一个新的位置, 与原对象之间不存在关系了。

常见的浅拷贝手段:

let a = {num: 1}  let b = {age: 19}
let A = Object.assign(a,b)

console.log(A == a)    // true 
console.log(A) // {num: 1, age: 19}

Array.slice(index) 也是一个浅拷贝 Array.slice不改变原数组, 返回一个新的数组 当Array只有一层的时候,是深拷贝;所以当原数据进行浅拷贝,改变r的r[1],而原数据arr中的arr[1]不会改变;

let arr = [1,2,3,4]
let r = arr.slice(0,2)
console.log(arr, r)
// [1, 2, 3, 4] (2) [1, 2]

展开运算符... 实现浅拷贝

let obj1 = { name: 'Chen', hobby: ['see a film', 'write the code', 'play basketball'] } 
let obj2 = {...obj1};

深拷贝的实现:

  1. JSON.parse(JSON.stringify())
  2. jQuery.extend()方法
  3. 手写递归方法:(递归方法实现深度克隆原理:遍历对象、数组直到里边都是基本数据类型,然后再去复制,就是深度拷贝)
// 检测数据类型的功能函数
const checkedType = (target) => Object.prototype.toString.call(target).replace(/\[object (\w+)\]/, "$1").toLowerCase();
// 实现深拷贝(Object/Array)
const clone = (target) => {
    let result;
    let type = checkedType(target);
    if(type === 'object') result = {};
    else if(type === 'array') result = [];
    else  return target;
    for (let key in target) {
        if(checkedType(target[key]) === 'object' || checkedType(target[key]) === 'array') {
            result[key] = clone(target[key]);
        } else {
            result[key] = target[key]; 
        }
    }
    return result;
}

2、两个由对象组成的数组,其中在长度小的数组中所有的对象的id都是唯一的, 在长度大的数组中,存在多个相同的id的对象, 如何在长度大的数组中找到所有与数组长度小的的对象相同的id的方法 , 实现方式有哪些?

实现方式一:

// 假设数组A是长度小的数组,数组B是长度大的数组
const result = [];
for (const objA of A) {
  for (const objB of B) {
    if (objA.id === objB.id) {
      result.push(objB);
    }
  }
}

这段代码会依次遍历 A 和 B 中的每个对象,并将它们的 id 进行比较。如果两个对象的 id 相同,就将 B 中的对象添加到结果数组中。

实现方式二:

如果数组 B 很大,可以考虑使用 Map 来存储 B 中的对象,以便更快地查找。具体实现方式可以参考以下代码:

// 假设数组A是长度小的数组,数组B是长度大的数组
const result = [];
const mapB = new Map(B.map(obj => [obj.id, obj]));
for (const objA of A) {
  const objB = mapB.get(objA.id);
  if (objB) {
    result.push(objB);
  }
}

这段代码会先将数组 B 转换为 Map 对象,其中键为对象的 id,值为对象本身。然后依次遍历 A 中的每个对象,在 Map 中查找对应的对象,如果存在就将其添加到结果数组中。

实现方式三:

// 假设数组A是长度小的数组,数组B是长度大的数组
const result = B.filter(objB => A.some(objA => objA.id === objB.id));

这段代码使用了 B 数组的 filter 方法和 A 数组的 some 方法。filter 方法会遍历 B 数组中的每个对象,并返回一个新的数组,其中包含满足条件的对象。some 方法会遍历 A 数组中的每个对象,只要有一个对象的 id 和当前 B 数组中的对象的 id 相同,就会返回 true。

这种实现方式比较简洁,但可能不太容易理解。如果需要更好的可读性和可维护性,建议使用前面提到的循环和条件语句或者哈希表(字典)来实现。

3、cookie\localStorage\sessionStorage三者的区别?

  • cookie: 其实最开始是服务器端用于记录用户状态的一种方式,由服务器设置,在客户端存储,然后每次发起同源请求时,发送给服务器端。cookie 最多能存储 4 k 数据,它的生存时间由 expires 属性指定,并且 cookie 只能被同源的页面访问共享。

  • sessionStorage: html5 提供的一种浏览器本地存储的方法,它借鉴了服务器端 session 的概念,代表的是一次会话中所保存的数据。它一般能够存储 5M 或者更大的数据,它在当前窗口关闭后就失效了,并且 sessionStorage 只能被同一个窗口的同源页面所访问共享。

  • localStorage: html5 提供的一种浏览器本地存储的方法,它一般也能够存储 5M 或者更大的数据。它和 sessionStorage 不同的是,除非手动删除它,否则它不会失效,并且 localStorage 也只能被同源页面所访问共享。

4、Promise的规范, 其实现链式调用的原理?

vue篇

  1. vue2中data为什么需要用一个函数返回?
  2. $set是用来干嘛的?
  3. vue2中的diff算法是怎么一回事?
  4. vue的数据劫持是怎么一回事?
  5. vue2中对数组的劫持是怎么处理的?
  6. vue3与vue2的区别主要体现在哪些方面?
  7. vue中在项目中会如何去做性能优化?

react篇

  1. react中的合成事件了解吗?
  2. react中的diff算法是怎么样做的?
  3. react中常用的hooks有哪些,其原理是什么?
  4. react中的redux的使用是怎么样的,其原理是什么?
  5. react中父子组件的数据和方法的相互调用有哪些方式?

浏览器篇

  1. 强缓存与协商缓存的区别?
  2. 浏览器的事件循环机制? node的eventLoop是咋样的?
  3. 常用的http状态码有哪些?
  4. 从输入url到页面显示发生了什么?
  5. 性能优化手段会用到哪些?