乐趣区

关于前端:面试必考-手撕代码系列一

前言

系列首发于公众号『前端进阶圈』,若不想错过更多精彩内容,请“星标”一下,敬请关注公众号最新消息。

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

手写深拷贝 (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);
    }
};

特殊字符形容:

  1. 问题标注 Q:(question)
  2. 答案标注 R:(result)
  3. 注意事项规范:A:(attention matters)
  4. 详情形容标注:D:(detail info)
  5. 总结标注:S:(summary)
  6. 剖析标注:Ana:(analysis)
  7. 提醒标注:T:(tips)

    往期举荐:

  8. 前端面试实录 HTML 篇
  9. 前端面试实录 CSS 篇
  10. JS 如何判断一个元素是否在可视区域内?
  11. Vue2、3 生命周期及作用?
  12. 排序算法:QuickSort
  13. 箭头函数与一般函数的区别?
  14. 这是你了解的 CSS 选择器权重吗?
  15. JS 中 call, apply, bind 概念、用法、区别及实现?
  16. 罕用位运算办法?
  17. Vue 数据监听 Object.definedProperty() 办法的实现
  18. 为什么 0.1+ 0.2 != 0.3,如何让其相等?
  19. 聊聊对 this 的了解?
  20. JavaScript 为什么要进行变量晋升,它导致了什么问题?

    最初:

  21. 欢送关注『前端进阶圈』公众号,一起摸索学习前端技术 ……
  22. 公众号回复 加群 或 扫码, 即可退出前端交流学习群,一起高兴摸鱼和学习 ……
  23. 公众号回复 加好友,即可添加为好友
退出移动版