面试必考: 手撕代码系列(一)

简介: 面试必考: 手撕代码系列(一)

面试必考: 手撕代码系列(一)


手写深拷贝 (deepClone)

/**
 * deepClone 深拷贝
 * @param {*} source 源对象(需要拷贝的对象)
 * @returns 新对象
 */
const deepClone = source => {
    // 存储结果
    const obj = {};
    // for...in 方法:遍历对象时 key 为对象的键;遍历数组时 key 为数组下标 index
    for (const key in source) {
        // Object.prototype.hasOwnProperty.call(); 方法是一个常用的,安全监测对象是否含有某个属性的方法,使用此方法可避免 hasOwnProperty 属性被污染或被重写的风险。
        if (Object.prototype.hasOwnProperty.call(source, key)) {
            // Object.prototype.toString.call(); 通过原型的方式判断一个值的类型
            // 为什么使用 xxx.slice(8, -1)?
            // 因为 Object.prototype.toString.call() 返回的值是 [object Object], 使用 slice 方法截取
            if (Object.prototype.toString.call(source[key]).slice(8, -1) === 'Object') {
                // 递归
                obj[key] = deepClone(source[key]);
            } else {
                // 赋值
                obj[key] = source[key];
            }
        }
    }
    return obj;
};
// test:
const a = {
    age: 12,
    otherInfo: {
        sex: 0,
    },
};
const b = deepClone(a);
b.age = 22;
b.otherInfo.sex = 1;
console.log('a------>', a); // a------> { age: 12, otherInfo: { sex: 0 } }
console.log('b------>', b); // b------> { age: 22, otherInfo: { sex: 1 } }

手写浅拷贝 (shallowClone)

  • • 逻辑同深拷贝类似,浅拷只会影响一层数据结构
/**
 * shallowClone 浅拷贝
 * @param {*} source 源对象(需要拷贝的对象)
 * @returns 新对象
 */
const shallowClone = source => {
    const obj = {};
    for (const key in source) {
        if (Object.prototype.hasOwnProperty.call(source, key)) {
            obj[key] = source[key];
        }
    }
    return obj;
};
// test:
const a = {
    age: 12,
    otherInfo: {
        sex: 0,
    },
};
const b = shallowClone(a);
b.age = 22;
b.otherInfo.sex = 1;
console.log('a------>', a); // a------> { age: 12, otherInfo: { sex: 1 } }
console.log('b------>', b); // b------> { age: 22, otherInfo: { sex: 1 } }

手写 new 操作符 (customNew)

/**
 * customNew new操作符
 * @param {*} fn 普通函数(!不能是箭头函数)
 * @param {*} rest 参数
 * @returns 新对象(类似于实例)
 */
const customNew = (fn, ...rest) => {
    // 1.创建一个新对象
    const obj = {};
    // 2.让新对象的隐士原型等于函数的显示原型
    obj.__proto__ = fn.prototype;
    // 3.绑定 this, 让函数的 this 指向这个新对象(也就是绑定一些属性)
    const res = fn.apply(obj, rest);
    // 4.判断返回
    return Object.prototype.toString.call(res).slice(8, -1) === 'Object' ? res : obj;
};
// test:
function Person(name, age) {
    this.name = name;
    this.age = age;
}
Person.prototype.getName = function () {
    return this.name;
};
const person = customNew(Person, 'John', 11);
console.log('person ------->', person); // person -------> Person { name: 'John', age: 11 }
console.log('person.getName() ------->', person.getName()); // person.getName() -------> John

手写节流 (throttle)

/**
 * throttle 节流
 * 某一段时间内只触发一次,按第一次来算
 * @param {*} fn 方法
 * @param {*} time 时间(默认 1500ms)
 * @returns
 */
const throttle = (fn, time = 1500) => {
    // 标记状态
    let flag = null;
    return function () {
        // 若 flag 为 true, 则继续执行,不做任何操作
        if (flag) return;
        // 更改标记状态
        flag = true;
        // 执行方法
        fn();
        // 定时器
        let timer = setTimeout(() => {
            // time 结束,修改 flag = false
            flag = false;
            // 清除定时器标记
            clearTimeout(timer);
        }, time);
    };
};

手写防抖 (debounce)

/**
 * debounce 防抖
 * 某一段时间内只触发一次,按最后一次来算
 * @param {*} fn 方法
 * @param {*} time 时间(默认 1500ms)
 * @returns
 */
const debounce = (fn, time = 1500) => {
    // 定期器标记
    let timer = null;
    return function () {
        // 若 timer 为 true, 则停止之前方法,重新开始
        timer && clearTimeout(timer);
        timer = setTimeout(() => {
            // 执行方法
            fn();
        }, time);
    }
};

特殊字符描述

问题标注 Q:(question)答案标注 R:(result)注意事项标准:A:(attention matters)详情描述标注:D:(detail info)总结标注:S:(summary)分析标注:Ana:(analysis)提示标注:T:(tips)

相关文章
|
7月前
|
前端开发
【面试题】如何使用ES6 ... 让代码优雅一点?
【面试题】如何使用ES6 ... 让代码优雅一点?
|
7月前
|
存储 前端开发 JavaScript
【面试题】你是如何让js 代码变得简洁的?
【面试题】你是如何让js 代码变得简洁的?
|
4月前
|
Java 编译器 C++
【Java基础面试一】、为什么Java代码可以实现一次编写、到处运行?
这篇文章解释了Java能够实现“一次编写,到处运行”的原因,主要归功于Java虚拟机(JVM),它能够在不同平台上将Java源代码编译成的字节码转换成对应平台的机器码,实现跨平台运行。
【Java基础面试一】、为什么Java代码可以实现一次编写、到处运行?
|
4月前
|
存储 缓存 Java
面试问Spring循环依赖?今天通过代码调试让你记住
该文章讨论了Spring框架中循环依赖的概念,并通过代码示例帮助读者理解这一概念。
面试问Spring循环依赖?今天通过代码调试让你记住
|
4月前
|
JavaScript 前端开发 程序员
JS小白请看!一招让你的面试成功率大大提高——规范代码
JS小白请看!一招让你的面试成功率大大提高——规范代码
|
7月前
|
缓存 监控 算法
Python性能优化面试:代码级、架构级与系统级优化
【4月更文挑战第19天】本文探讨了Python性能优化面试的重点,包括代码级、架构级和系统级优化。代码级优化涉及时间复杂度、空间复杂度分析,使用内置数据结构和性能分析工具。易错点包括过度优化和滥用全局变量。架构级优化关注异步编程、缓存策略和分布式系统,强调合理利用异步和缓存。系统级优化则涵盖操作系统原理、Python虚拟机优化和服务器调优,需注意监控系统资源和使用编译器加速。面试者应全面理解这些层面,以提高程序性能和面试竞争力。
88 1
Python性能优化面试:代码级、架构级与系统级优化
|
7月前
|
数据采集 数据挖掘 Python
最全妙不可言。写出优雅的 Python 代码的七条重要技巧,2024年最新被面试官怼了还有戏吗
最全妙不可言。写出优雅的 Python 代码的七条重要技巧,2024年最新被面试官怼了还有戏吗
|
6月前
|
存储 算法 Java
面试高频算法题汇总「图文解析 + 教学视频 + 范例代码」之 二分 + 哈希表 + 堆 + 优先队列 合集
面试高频算法题汇总「图文解析 + 教学视频 + 范例代码」之 二分 + 哈希表 + 堆 + 优先队列 合集
|
7月前
|
数据采集 XML 程序员
最新用Python做垃圾分类_python垃圾分类代码用key和format,5年经验Python程序员面试27天
最新用Python做垃圾分类_python垃圾分类代码用key和format,5年经验Python程序员面试27天
最新用Python做垃圾分类_python垃圾分类代码用key和format,5年经验Python程序员面试27天
|
7月前
|
数据采集 机器学习/深度学习 人工智能
最新用python代码画爱心,来自程序猿的浪漫~_python画爱心代码(1),2024年最新面试简历模板免费
最新用python代码画爱心,来自程序猿的浪漫~_python画爱心代码(1),2024年最新面试简历模板免费
最新用python代码画爱心,来自程序猿的浪漫~_python画爱心代码(1),2024年最新面试简历模板免费

热门文章

最新文章

相关实验场景

更多