js面试总结(一)

125 阅读3分钟

js原始类型有哪些?

js原始类型:

  • Number
  • String
  • symbol
  • null
  • undefined
  • Boolean
  • BigInt

数组的方法有哪些?

这里我们按照增删改查来回答更能回答完全

  1. 增:push、unshift、splice、concat;
  2. 删:pop、shift、splice、slice;
  3. 改:reverse、sort、copyWithin
  4. 查:includes、indexOf、find、some、every

建议每个方法的用法都去熟悉一下。

js深拷贝与浅拷贝

浅拷贝

定义

浅拷贝是指创建一个新对象,这个新对象具有原始对象属性值的一份精确拷贝。如果属性是基本类型(如字符串、数字、布尔值等),拷贝的就是基本类型的值;如果属性是引用类型(如对象、数组等),拷贝的就是内存地址,也就是说,浅拷贝得到的新对象中的引用类型属性与原始对象中的引用类型属性指向同一个内存地址。
与深拷贝的主要区别就在于对引用类型属性的拷贝,说白了当有引用类型时浅拷贝就是与原对象共用,互相影响;而深拷贝则不共用也不互相影响

实现浅拷贝的方法

  1. const newObj = Object.assign(obj) -- 对象方法
  2. const newObj = {...obj} -- 对象方法
  3. const newArr = arr.slice() -- 数组方法
  4. 手写
function shallowCopy(obj) {
    let newObj = {}
    for (let key in obj) {
        if (obj.hasOwnProperty(key)) {
            newObj[key] = obj[key]
        }
    }
    return newObj;
}
  • 这里有一个小细节,就是hasOwnProperty是用来判断是否为自有属性,避免从原型链继承属性

深拷贝

定义

深拷贝是指创建一个新对象,并递归地复制原始对象的所有属性,包括基本类型和引用类型的属性。这意味着对于引用类型的属性,会创建一个新的对象,并复制原始对象中的属性值,而不仅仅复制内存地址。
注意,深拷贝完全独立于原对象,不互相影响

实现深拷贝的方法

  1. let newObj = JSON.parse(JSON.StringIfy(obj)) -- 注意,这个方法不能处理undefined、symbol、function和循环引用的对象
  2. let newObj = structuredClone(obj) -- 注意,这个方法无法拷贝symbol、function和循环引用的对象
  3. 信息管道
function deepCopy(obj){
    return new Promise((resolve) => {
        const { port1, port2 } = new MessageChannel() 
        port1.postMessage(obj)
        port2.onmessage = (msg) => {
            resolve(msg.data)
        }
    })
}

-- 这个方法实现了十分完善的深拷贝

  1. 手写
function deepCopy(obj) {
    let newObj = {}
    for (let key in obj){
        if (obj.hasOwnProperty(key)) {
            if (typeof obj[key] !== 'object' || obj[key] !== null) {
                newObj[key] = obj[key]
            }else{
                deepCopy(newObj[key])
            }
        }
    }
    return newObj;
}

call、apply和bind区别

call、bind、apply功能都是改变this的指向,但是三者的使用方法不同:

  • call和apply的第一个参数都是对象,让this指向这个对象;第二个参数开始就不同了,call是可以接收任意个参数,apply则是以数组或类数组的形式接收。
Function.call(obj,...args) // es6写法
或 Function.call(obj,[,arg1[,arg2[,arg3[...]]]])
Function.apply(obj,[argArray])
  • bind方法与call、bind类似,也能改变this的指向。不同的是,bind方法返回的是函数,需要手动调用。
Function.bind(obj,...args)

如果面试官问到手写call、apply和bind时,推荐看下面这篇文章: juejin.cn/post/712823…

map 和 foreach 的区别

  1. map会返回一个新数组,foreach不会; 这里手写一下,就会更清楚:
function myForeach (array, callback) {
    for (let i = 0; i< array.length; i++) {
        callback(array[i], i, array)
    }
}
function myMap (array, callback) {
    let newArray = []
    for (let i = 0; i < array.length; i++) {
        newArray[i].push(callback(array[i], i, array))
    }
    return newArray
}
  1. foreach可以使用return语句一样跳过本次迭代,而map不可以
  2. foreach不支持链式调用,map支持

for in 和 for of的区别

  • for in 遍历对象的索引(下标),返回的结果是键(key);
  • for of 遍历对象的值,返回的结果是值(value)