面经之js原生实现

1、实现深拷贝

<script>
   let obj={
    a:'name',
    b:1,
    arr:['x','y','z'],
    innerobj:{
        c:2
    }
   }

    //实现深拷贝
   function deepClone(source){
    //判断要复制的类型
    const targetObj=source.constructor === Array ? [] : {};
    //开始赋值,对于每条属性
    for(let keys in source){
        //如果还有引用数据类型
        if(source[keys] && source[keys] === 'object'){
            //递归
            targetObj[keys]=deepClone(source[keys]);
        }else{
            //该条属性为基本数据类型,直接赋值其值
            targetObj[keys]=source[keys];
        }
    }
    return targetObj
   }
   let obj2=deepClone(obj);
   console.log(obj);
   console.log(obj2);
</script>

2、防抖

  • 触发高频事件后n秒内函数只会执行一次,如果n秒内高频事件再次被触发,则会重新计算时间
  • 防抖场景
    • 登录、发信息时防止用户点击太快而发送多次请求
    • 调整浏览器窗口时,防止resize次数过于频繁而导致计算过多
    • 文本编辑器实时保存,当无任何更改操作后进行保存
<body>
    <input type="text" id="search">
</body>
<script>
    // 封装实现防抖的函数
    function debounce (func,wait){  //第一个参数为操作函数,第二个参数为时间间隔(单位毫秒)
        let timer = null; //闭包使用的外部变量
        return function(){ //闭包
            if(timer) clearTimeout(timer); //去掉之前的无效任务
            //创建新任务
            timer = setTimeout(()=>{
                // func() //直接执行函数 存在作用域问题
                func.call(this)
                // func.apply(this,arguments)
            },wait)
        }
    }
    //eg.
    function count(){
        console.log("开始发送请求...");
    }
    document.getElementById("search").onkeyup = debounce(count,2000)
 </script>

3、节流 

  • 高频事件触发,但在n秒内只执行一次,这样稀释函数执行的频率
  • 节流场景
    • scroll事件,每隔一秒计算一次位置信息
    • 浏览器播放事件,每隔一秒计算一次进度信息
<body>
    <div id="content" style="width: 100%;height: 50px;background-color: aqua;"></div>
</body>
<script>
    let num = 1;
    // 1、封装实现节流的函数
    function throtttle1 (func,wait){  //第一个参数为操作函数,第二个参数为时间间隔(单位毫秒)
        let timer = null; //闭包使用的外部变量
        return function(){ //闭包
            if(!timer){ //创建新的定时任务
                timer = setTimeout(()=>{
                   timer = null; //清除任务
                    // func() //直接执行函数 存在作用域问题
                    func.call(this)
                    // func.apply(this,arguments)
                },wait)
            }             
        }
    }

    // 2、通过时间戳实现
    function throtttle2 (func,wait){  //第一个参数为操作函数,第二个参数为时间间隔(单位毫秒)
        let pre = 0; //闭包使用的外部变量
        return function(){ //闭包
            let now = Date.now()
            if(now - pre > wait){ //创建新的定时任务
                // func() //直接执行函数 存在作用域问题
                func.call(this)
                // func.apply(this,arguments)
                
                //重置pre
                pre = now
            }            
        }
    }
    //eg.
    function count(){
        console.log("开始发送请求...");
        document.getElementById("content").innerHTML = num++
    }
    document.getElementById("content").onclick = throtttle2(count,2000)
 </script>

 4、懒加载

5、函数柯里化

参数复用
  • 指将一个接收多个参数的函数 变为 接收一个参数返回一个函数的 固定形式 ——> 这样对于重复的参数可以进行更好的复用 比如网址中 " https:// " 
<script>
    //拼接 https:// www.baidu.com /id
    function urlCreate(p1 ,p2,p3){
        return `${p1}${p2}${p3}`
    }
    let urlnow = urlCreate('https://','www.baidu.com','/id')
    console.log(urlnow);

    // ——> 进行参数p1的复用
    function urlCreate2(p1){
        return function(p2,p3){
            return `${p1}${p2}${p3}`
        }
    }
    urlnow = urlCreate2('https://');
    let urlthen1 = urlnow('www.baidu.com','/id')
    let urlthen2 = urlnow('www.baidu.com','/name')
    console.log(urlthen1,urlthen2);
</script>
提前确认 / 提前返回
延迟执行
  • add(1)(2)(3) = 6
  • add(1,2,3)(4) = 10
  • add(1)(2)(3)(4)(5) = 15
<script>
   function add(){
    //将传入的不定参数转为数组对象
    let args = Array.prototype.slice.call(arguments)
    let inner = function(){  
        //这个内部函数用来接收第二次传入的参数 也就是第二个括号
        args.push(...arguments) //将第二个括号的参数加入到第一个括号的参数里面

        //每次增加一个括号,我们都需要增加一个内部函数,
          // ——> 通过递归实现,再内部函数里进行自己调用自己
        return inner 
    }
    
    //原本的函数会被隐式转换为字符串显示
    //把内部函数的toString方法进行修改 可不返回原本应该输出函数字符串内容(默认内容)而返回自定义的
    //这样返回的类型还是函数function
    inner.toString = function(){
        return args.reduce(function(prev,cur){ //将所有参数求和
            return prev + cur
        })    
    }
    return inner
   }
   let a = add(1,2,3).toString()
   let b = add(1)(2)(3).toString()
   console.log(a); //6
   console.log(b); //6
</script>

 JavaScript函数柯里化 - Web前端工程师面试题讲解_哔哩哔哩_bilibili

6、实现 call apply bind

call

apply

bind 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

prominent.949

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值