8月更文挑战 | 前端Js手写题汇总(一)

102 阅读2分钟

这是我参与8月更文挑战的第6天,活动详情查看:8月更文挑战

1.防抖函数

防抖函数特点:

用于高频触发事件,点击按钮后未操作,在N秒后触发一次事件,若N秒内重新点击,则重新计时
应用场景:搜索框输入、输入验证、Resize
/*
    基础版本
*/

function debounce(func,wait){
    let timer = null;
    return funtion(){
        if(timer){
            clearTimeout(timer);  //重复触发则清空定时器,重新设置
        }
        //设置定时任务
        setTimeout(()=>{
            func.call(this.arguments);
        },wait)
    }
}
/*
    改进版本:
    可设置是否立即触发
    可能有返回值
    可取消
*/

function debounce(func,wait,immediate){
    var timer,result;
    
    var debounced = function(){
        if(timer) clearTimeout(timer)
        if(immediate){
            //立即执行
            if(!timer) func.call(this,arguments)
        }else{
            //防抖
            timer = setTimeout(()=>{
                func.call(this,arguments)
            })
        }
        return result;
    }
    
    debounced.cancel = function(){
        clearTimeout(timer);
        timer = null;
    }
    
    return debounced;
}

2.节流函数

节流函数特点:

用于高频触发事件,N秒内不论点击多少次,都只触发一次
应用场景:模糊搜索、懒加载
/*
    参数为秒
*/
function throttle(func,delay){
    let canRun = true;
    return function(){
        if(canRun == false) return;  //未达到时间,不能够运行,直接返回
        canRun = false;  //将canRun修改为false,防止持续点击造成多次触发
        setTimeout(()=>{
            func.call(this,arguments);
            canRun = true;  //执行完成后,将标志设置为true,下一次触发后重新设置定时器
        },delay)
    }
}
/*
    时间戳节流(立即执行一次,随后按wait执行)
*/
function throttle(func,wait){
    let pre = 0;
    return function(){
        let now = Date.now();
        if(now - pre = wait){
            //第一次if会立即执行一次,条件成立
            func.call(this,arguments);
            pre = now;
        }
    }
}

3.类型判断

类型判断最佳方法:Object.prototype.toString.call(arg)

function getType(arg){
    return Object.prototype.toString.call(arg).slice(8,-1).toLowerCase();
}

4.浅拷贝

  • 针对基本数据类型:深拷贝,不会被修改行为影响
  • 针对引用数据类型:拷贝出的引用数据类型与被拷贝的对象中的引用对象共享空间,会相互影响
/*
    方法一:Object.assign(target,source)
*/

var person = {
    "name":"tony",
    "age":21,
    tech:{
        "react":false
    }
}
let personCopy = Object.assign({},person)

personCopy.age = 20;
console.log(person.age) //21
console.log(personCopy.age) //20

console.log(person.tech.react) //false
personCopy.tech.react = true
console.log(person.tech.react) //true
console.log(personCopy.tech.react)//true

/*
    方法二:ES6展开操作符
*/

var person = {
    "name":"tony",
    "age":21,
    tech:{
        "react":false
    }
}

let personCopy = {...person}

5.深拷贝

深拷贝为引用数据类型开辟了新的内存空间,因此拷贝过后不受其他赋值影响

方法:

  • JSON.parse(JSON.stringfy(obj))
  • 递归
/*
    方法一:JSON.parse(JSON.stringfy(obj))
*/

var person = {
    "name":"tony",
    "age":21,
    tech:{
        "react":false
    }
}

let tony = JSON.parse(JSON.stringfy(person))
console.log(tony)

/*
    方法二:递归(仅考虑了普通对象,未考虑内置对象以及函数)
*/

function deepClone(obj) {
    if (typeof obj !== 'object') return;
    var newObj = obj instanceof Array ? [] : {};
    for (var key in obj) {
        if (obj.hasOwnProperty(key)) {
            newObj[key] = typeof obj[key] === 'object' ? deepClone(obj[key]) : obj[key];
        }
    }
    return newObj;
}