js底层面试题+代码(机试)

1、 new操作符都做了哪些事,手写new操作符

function myNew(func,...args){
  //1.创建一个新的空对象
  const newObj = {}
  //2.将新对象的原型指向构造函数的原型
  newObj._proto_ = func.prototype
  //3.将构造函数的this指向新对象
  let result = apply(newObj,args)
  //4.处理构造函数的返回值,根据返回值进行判断,判断是基本类型还是引用类型
  return result instanceof Object ? result : newObj
}

2、闭包的理解,手写一个闭包函数使用场景

  • 闭包就是能够读取其他函数内部变量的函数
  • 闭包是为了设计私有方法和变量,实现js封装
  • 函数嵌套函数,内部函数可以访问外部函数的变量
//1.解决for循环问题
for(var i = 0;i<5,i++){
  (function(j){
      setTimeOut(function(){
        console.log(j) // 0 1 2 3 4
      },500)
  })(i)
}

3、手写防抖和节流函数

  • 防抖:应用于搜索框输入、窗口大小调整、表单提交事件
function debonce(func,delay){
  let timer = null
  return function(...args){
    if(timer) clearTimeout(timer);
    timer = setTimeout(()=>{
        func.apply(this,args) //延迟执行
      },delay)
  }
}
const searchInput = document.getElementById("myInput")
const fetchData = () => console.log("发送请求")
searchInput.addEventListener("input",debonce(fetchData,500))
  • 节流:应用于滚动加载、鼠标移动事件、高频触发事件
function throttle(func,delay){
  let timer = null
  return function(...args){
    if(!timer){
      timer = setTimeout(()=>{
        func.apply(this,args)
        timer = null
      },delay)
    }
  }
}

window.addEventListener("scroll",throttle(()=>{
  console.log("滚动加载数据")
},1000))

4、js实现快速排序算法

1.快速排序是一种高效的排序算法,采用分治策略

function quickSort(arr) {
  // 如果数组长度小于等于1,直接返回(递归的终止条件)
  if (arr.length <= 1) {
    return arr;
  }

  // 选择基准值(pivot),这里选择中间元素
  const pivotIndex = Math.floor(arr.length / 2);
  const pivot = arr[pivotIndex];
  
  // 定义左右两个数组
  const left = [];
  const right = [];

  // 遍历数组,将元素分配到左右两个数组
  for (let i = 0; i < arr.length; i++) {
    if (i === pivotIndex) continue; // 跳过基准元素
    
    if (arr[i] < pivot) {
      left.push(arr[i]);
    } else {
      right.push(arr[i]);
    }
  }

  // 递归调用并合并结果
  return [...quickSort(left), pivot, ...quickSort(right)];
}

// 使用示例
const unsortedArray = [3, 6, 8, 10, 1, 2, 1];
const sortedArray = quickSort(unsortedArray);
console.log(sortedArray); // 输出: [1, 1, 2, 3, 6, 8, 10]

2.为了更高效地实现快速排序,通常使用Lomuto分区方案,即在数组中选择最后一个元素作为基准值,并通过一次遍历来重新排列数组

function quickSort(arr, left = 0, right = arr.length - 1){
  if(left < right){
    const pivotIndex = partition(arr, left, right);
    quickSort(arr, left, pivotIndex - 1);
    quickSort(arr, pivotIndex + 1, right);
  }
  return arr
}
function partition(arr, left, right){
  const pivot = arr[right]; //选择最右边元素作为基准
  let i = left;
  for(let j = left; j < right; j++){
    if(arr[j] < pivot){
      [arr[i], arr[j]] = [arr[j], arr[i]]; //交换元素
      i++;
    }
  }
   
  [arr[i], arr[right]] = [arr[right], arr[i]]; //将基准放到正确位置
  return i;
}

//使用示例
const array = [3,6,8,10,1,2,1]
quickSort(array);
console.log(array);

5、实现浅拷贝和深拷贝

  • 浅拷贝方法
//1.Object.assign()
const obj = { a: 1, b: { c: 2 } };
const shallowCopy = Object.assign({}, obj);

shallowCopy.b.c = 3; // 修改嵌套对象
console.log(obj.b.c); // 3(原对象也被修改)

//2. 扩展运算符 ...
const obj = { a: 1, b: { c: 2 } };
const shallowCopy = { ...obj };

shallowCopy.b.c = 3;
console.log(obj.b.c); // 3(原对象也被修改)

//3.数组的slice()方法
const arr = [1, 2, { a: 3 }];
const shallowCopy = arr.slice();

shallowCopy[2].a = 4;
console.log(arr[2].a); // 4(原数组也被修改)

//4.Array.from()
const arr = [1, 2, { a: 3 }];
const shallowCopy = Array.from(arr);

shallowCopy[2].a = 4;
console.log(arr[2].a); // 4(原数组也被修改)

//5. 使用赋值运算符(=)进行拷贝
const a = [1, 2, 3];
const b = a; // 浅拷贝
b[0] = 4;
console.log(a); // [4, 2, 3]
console.log(b); // [4, 2, 3]
  • 深拷贝方法
//1. JSON.parase(JSON.stringify(obj))
const obj = { a: 1, b: { c: 2 } };
const deepCopy = JSON.parse(JSON.stringify(obj));

deepCopy.b.c = 3;
console.log(obj.b.c); // 2(原对象不受影响)

缺点:
不能复制 undefined、function、Symbol。
不能处理循环引用(如 obj.self = obj)。
会丢失 Date 对象(转为字符串)。

//2.递归手动实现
function deepClone(obj, hash = new WeakMap()) {
  if (obj === null || typeof obj !== "object") return obj;
  if (hash.has(obj)) return hash.get(obj); // 解决循环引用

  const clone = Array.isArray(obj) ? [] : {};
  hash.set(obj, clone);

  for (const key in obj) {
    if (obj.hasOwnProperty(key)) {
      clone[key] = deepClone(obj[key], hash);
    }
  }

  return clone;
}

// 测试
const obj = { a: 1, b: { c: 2 }, d: [3, 4] };
const deepCopy = deepClone(obj);

deepCopy.b.c = 99;
deepCopy.d.push(5);
console.log(obj); // { a: 1, b: { c: 2 }, d: [3, 4] }(原对象不变)
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容