某东大厂面试js手写题【手写代码附带注释,放心食用,博主亲测】

简介: 某东大厂面试js手写题【手写代码附带注释,放心食用,博主亲测】

前言

hello world欢迎来到前端的新世界


😜当前文章系列专栏:前端面试

🐱‍👓博主在前端领域还有很多知识和技术需要掌握,正在不断努力填补技术短板。(如果出现错误,感谢大家指出)🌹

💖感谢大家支持!您的观看就是作者创作的动力

js实现push方法


let Arr = [1, 2, 3];
Array.prototype.push = function (...items) {  // 通过Array.prototype.push的这个属性我们定义的方法顶替
    const len = this.length;  // 当前数组的长度
    const itemCount = items.length;  // 值的长度
    for (let i = 0; i < itemCount; i++) {  // 把每一个值都进行循环
        this[len + i] = items[i];  // 把当前数组长度+i,i是循环的我们要添加的itemCount的长度的循环,第一个是1到我们数组的最长的长度根据我们的数组的特性,根据没有的索引进行添加值来操作,然后从而实现push添加
    }
    this.length = len + itemCount;  // 更新数组长度
    return this.length;  // 返回数组更新长度
}
Arr.push(99)  // 调用方法
console.log(Arr)  // 查看数组调用后的后果


  • 这里的this代表的当前的数组也就是下图中的这里,arr这里。


  • 然后通过重新获取我们数组的长度(因为我们在循环添加数组的新属性的时候,我们的数组添加的过程中是用的 this[len + i] = items[i] 这种形式; JavaScript 中的数组是一种特殊的对象,可以动态地添加属性(也就是索引)。当你使用一个不存在的索引访问或修改数组时,JavaScript 会自动将它作为一个新的属性添加到数组对象上,并为其赋予相应的值。


  • 然后就是值 我们传入值的长度


  • 然后就是循环 这里大家应该懂吧,就是用let 声明一个i 然后循环条件就是i<传入值的长度的时候,我们的i++


  • 循环的内容使用this[当前数组长度 + i] = 传入的值[i]


  • 然后循环完后,是通过this.length 来确定我们当前数组的长度,当前数组长度 + 我们传入的数组的长度,就是我们当前数组长度


  • 然后 返回最终我们的数组长度



js实现订阅发布


// 
// 定义一个主题类 Subject
class Subject {
    constructor() {
        this.observers = []; // 初始化观察者数组
    }
    // 添加观察者
    addObserver(observer){
        this.observers.push(observer); // 将新的观察者添加到观察者数组中
    }
    // 删除观察者
    removeObserver(observer){
        this.observers = this.observers.filter(obs => obs !== observer); // 通过过滤将特定的观察者从数组中移除
    }
    // 状态变化通知观察者
    notify(data){
        this.observers.forEach(observer => {
            observer.update(data); // 遍历观察者数组,调用每个观察者的 update 方法
        });
    }
}
// 定义一个观察者类 Observer
class Observer {
    update(data){
        console.log(`数据:${data}`); // 当接收到主题状态变化通知时,执行 update 方法来处理数据
    }
}
const subject = new Subject(); // 创建一个主题实例
const observerOne = new Observer(); // 创建第一个观察者实例
const observerTwo = new Observer(); // 创建第二个观察者实例
subject.addObserver(observerOne); // 将第一个观察者添加到主题的观察者数组中
subject.addObserver(observerTwo); // 将第二个观察者添加到主题的观察者数组中
subject.removeObserver(observerTwo); // 从主题的观察者数组中移除第二个观察者
subject.notify("hello word lpz"); // 主题状态发生变化,通知所有的观察者进行更新处理


手写防抖节流


// 节流函数
function throttle(fn, delay) {
  let timer = null; // 设置一个初始值为 null 的定时器变量
  let lastTime = 0; // 这里的 lastTime 变量用于记录上一次执行函数的时间戳
  return function(...args) { // 返回一个新的函数
    const now = performance.now(); // 获取当前时间戳
    const remainingTime = delay - (now - lastTime); // 计算距离上次执行函数剩余的时间
    if (remainingTime <= 0) { // 如果剩余时间小于等于 0,则立即执行函数
      if (timer) { // 如果存在已经设置的定时器,则清除它
        clearTimeout(timer);
        timer = null;
      }
      fn(...args); // 执行函数
      lastTime = now; // 更新上一次执行函数的时间戳
    } else if (!timer) { // 如果剩余时间大于 0,且不存在已经设置的定时器,则设置定时器
      timer = setTimeout(() => { // 延迟剩余时间后执行函数
        fn(...args);
        lastTime = performance.now(); // 更新上一次执行函数的时间戳
        timer = null; // 清空定时器变量
      }, remainingTime);
    }
  };
}
function handle() {
  console.log("触发");
}
let fn = throttle(handle, 2000); // 使用节流函数包装 handle 函数
fn(); // 第一次执行
// 监听滚动事件,在滚动过程中多次触发函数
window.addEventListener("scroll", fn);


手写reduce方法


Array.prototype.reduce = function(callback, initialValue) {
    // 首先判断数组是否为空,并且判断回调函数是否为函数类型
    if (this.length === 0 && typeof callback !== 'function') {
      throw new TypeError('Array is empty and callback is not a function');
    }
    let accumulator = initialValue === undefined ? this[0] : initialValue; // 初始化累加器的值
    for (let i = initialValue === undefined ? 1 : 0; i < this.length; i++) { // 从初始值开始迭代数组
      accumulator = callback(accumulator, this[i], i, this); // 调用回调函数进行累加器值的更新
    }
    return accumulator; // 返回最终累加器的值
  };
  // 测试
  const array = [1, 2, 3, 4, 5];
  const sum = array.reduce((acc, cur) => acc + cur, 0);
  console.log(sum); // 输出 15,即 1 + 2 + 3 + 4 + 5 的和


深拷贝


function deepClone(obj) { // 定义一个函数 deepClone,接受一个对象作为参数
    if (obj === null) return null; // 如果传入的对象为 null,直接返回 null
    const type = typeof obj; // 获取 obj 的数据类型
    if (type !== 'object' && type !== 'function') return obj; // 如果 obj 是基本数据类型或函数类型,直接返回 obj
    const clone = Array.isArray(obj) ? [] : {}; // 创建一个新的空对象或数组
    for (let key in obj) { // 遍历 obj 的属性
        if (Object.hasOwnProperty.call(obj, key)) { // 判断属性是否属于 obj 对象本身
            clone[key] = deepClone(obj[key]); // 递归调用 deepClone 函数,将 obj 对应属性的值赋值给 clone 对应的属性
        }
    }
    return clone; // 返回深拷贝后的对象
}
var a = [1,2,3];
var b = deepClone(a);
b.push(5,5)
console.log(a)
// let b =  deepClone(a);


es5去重


// es5 数组去重
function arrfilter(arr:any[]){
    let res = arr.filter((item,index)=>{
        console.log(arr.indexOf(item) === index,item,index,arr.indexOf(item))
        return arr.indexOf(item) === index
    })
    return res;
}
console.log(arrfilter(["张三","张三","张三","找死","李斯特"]))


数组多维数组去重排序


// 数组多维数组去重排序
function numberArrFilter(arr) {
  let newArr = new Set(arr); // 去重把数组转换为set对象
  let setArr = Array.from(newArr) // 再把set对象转换为数组对象
  return setArr.sort((a, b) => { // 然后返回排序的结果
    return a - b;
  })
}
// 数组扁平化 通过递归循环
function flattenArray(arr) {
  return arr.reduce((result, item) => { // 使用 reduce() 方法对数组进行迭代处理
    if (Array.isArray(item)) { // 如果当前元素是数组
      result.push(...flattenArray(item)); // 递归调用扁平化函数,将子数组扁平化后的结果展开并添加到结果数组中
    } else { // 如果当前元素不是数组
      result.push(item); // 直接将元素添加到结果数组中
    }
    return result; // 返回累积的结果数组
  }, []); // 初始值是一个空数组
}
console.log(numberArrFilter(flattenArray([[1, 2, 3], [4, 5, [1, 2, 3, 4, 5, 6, 7, 8, 9, 10], 6], [1, 2, 3], [1, 2, 3], [1, 2, 3]])))


简单递归实现树形结构输出遍历


// 递归遍历树形结构
function getTree(data) {
    console.log(data.value);
    if (data.children) {
        data.children.forEach(item => getTree(item));
    }
}
// 创建一个简单的树结构
const tree = {
    value: 1,
    children: [
        {
            value: 2,
            children: [
                { value: 4 },
                { value: 5 }
            ]
        },
        {
            value: 3,
            children: [
                { value: 6 },
                { value: 7 }
            ]
        }
    ]
};
getTree(tree);


后言

创作不易,要是本文章对广大读者有那么一点点帮助 不妨三连支持一下,您的鼓励就是博主创作的动力


目录
相关文章
|
2月前
|
JavaScript 前端开发 安全
【逆向】Python 调用 JS 代码实战:使用 pyexecjs 与 Node.js 无缝衔接
本文介绍了如何使用 Python 的轻量级库 `pyexecjs` 调用 JavaScript 代码,并结合 Node.js 实现完整的执行流程。内容涵盖环境搭建、基本使用、常见问题解决方案及爬虫逆向分析中的实战技巧,帮助开发者在 Python 中高效处理 JS 逻辑。
|
4月前
|
JavaScript 前端开发 算法
流量分发代码实战|学会用JS控制用户访问路径
流量分发工具(Traffic Distributor),又称跳转器或负载均衡器,可通过JavaScript按预设规则将用户随机引导至不同网站,适用于SEO优化、广告投放、A/B测试等场景。本文分享一段不到百行的JS代码,实现智能、隐蔽的流量控制,并附完整示例与算法解析。
140 1
|
5月前
|
人工智能 前端开发 Java
Java 面试资料中相关代码使用方法与组件封装方法解析
这是一份详尽的Java面试资料代码指南,涵盖使用方法与组件封装技巧。内容包括环境准备(JDK 8+、Maven/Gradle)、核心类示例(问题管理、学习进度跟踪)、Web应用部署(Spring Boot、前端框架)、单元测试及API封装。通过问题库管理、数据访问组件、学习进度服务和REST接口等模块化设计,帮助开发者高效组织与复用功能,同时支持扩展如用户认证、AI推荐等功能。适用于Java核心技术学习与面试备考,提升编程与设计能力。资源链接:[点此下载](https://pan.quark.cn/s/14fcf913bae6)。
139 6
Java 面试资料中相关代码使用方法与组件封装方法解析
|
5月前
|
JavaScript 前端开发
怀孕b超单子在线制作,p图一键生成怀孕,JS代码装逼娱乐
模拟B超单的视觉效果,包含随机生成的胎儿图像、医疗文本信息和医院标志。请注意这仅用于前端开发学习
|
5月前
|
JavaScript
JS代码的一些常用优化写法
JS代码的一些常用优化写法
107 0
|
7月前
|
存储 JavaScript 前端开发
在NodeJS中使用npm包进行JS代码的混淆加密
总的来说,使用“javascript-obfuscator”包可以帮助我们在Node.js中轻松地混淆JavaScript代码。通过合理的配置,我们可以使混淆后的代码更难以理解,从而提高代码的保密性。
674 9
|
8月前
|
前端开发 JavaScript
【Javascript系列】Terser除了压缩代码之外,还有优化代码的功能
Terser 是一款广泛应用于前端开发的 JavaScript 解析器和压缩工具,常被视为 Uglify-es 的替代品。它不仅能高效压缩代码体积,还能优化代码逻辑,提升可靠性。例如,在调试中发现,Terser 压缩后的代码对删除功能确认框逻辑进行了优化。常用参数包括 `compress`(启用压缩)、`mangle`(变量名混淆)和 `output`(输出配置)。更多高级用法可参考官方文档。
619 11
|
8月前
|
JavaScript 前端开发 算法
JavaScript 中通过Array.sort() 实现多字段排序、排序稳定性、随机排序洗牌算法、优化排序性能,JS中排序算法的使用详解(附实际应用代码)
Array.sort() 是一个功能强大的方法,通过自定义的比较函数,可以处理各种复杂的排序逻辑。无论是简单的数字排序,还是多字段、嵌套对象、分组排序等高级应用,Array.sort() 都能胜任。同时,通过性能优化技巧(如映射排序)和结合其他数组方法(如 reduce),Array.sort() 可以用来实现高效的数据处理逻辑。 只有锻炼思维才能可持续地解决问题,只有思维才是真正值得学习和分享的核心要素。如果这篇博客能给您带来一点帮助,麻烦您点个赞支持一下,还可以收藏起来以备不时之需,有疑问和错误欢迎在评论区指出~
|
8月前
|
JavaScript 前端开发 API
JavaScript中通过array.map()实现数据转换、创建派生数组、异步数据流处理、复杂API请求、DOM操作、搜索和过滤等,array.map()的使用详解(附实际应用代码)
array.map()可以用来数据转换、创建派生数组、应用函数、链式调用、异步数据流处理、复杂API请求梳理、提供DOM操作、用来搜索和过滤等,比for好用太多了,主要是写法简单,并且非常直观,并且能提升代码的可读性,也就提升了Long Term代码的可维护性。 只有锻炼思维才能可持续地解决问题,只有思维才是真正值得学习和分享的核心要素。如果这篇博客能给您带来一点帮助,麻烦您点个赞支持一下,还可以收藏起来以备不时之需,有疑问和错误欢迎在评论区指出~
|
8月前
|
移动开发 运维 供应链
通过array.some()实现权限检查、表单验证、库存管理、内容审查和数据处理;js数组元素检查的方法,some()的使用详解,array.some与array.every的区别(附实际应用代码)
array.some()可以用来权限检查、表单验证、库存管理、内容审查和数据处理等数据校验工作,核心在于利用其短路机制,速度更快,节约性能。 博客不应该只有代码和解决方案,重点应该在于给出解决方案的同时分享思维模式,只有思维才能可持续地解决问题,只有思维才是真正值得学习和分享的核心要素。如果这篇博客能给您带来一点帮助,麻烦您点个赞支持一下,还可以收藏起来以备不时之需,有疑问和错误欢迎在评论区指出~
下一篇
oss云网关配置