JS基础防抖节流

举报
江咏之 发表于 2021/11/23 00:14:20 2021/11/23
【摘要】 一、call,apply,bind call,apply,bind都是用于改变this指向的 区别: 传参不同 call用逗号分隔的形式传参 函数名.call(目标对象,参数1,参数2,…参数n...

一、call,apply,bind

call,apply,bind都是用于改变this指向的

区别:

传参不同

call用逗号分隔的形式传参

函数名.call(目标对象,参数1,参数2,…参数n)
例如:getName.call(obj,‘王五’,25,‘北京’)

  
 
  • 1
  • 2

apply参数用数组的形式传递

函数名.apply(目标对象,[参数1,参数2,…参数n])
例如:getName.apply(obj,[‘王五11,25,‘上海’])

  
 
  • 1
  • 2

bind用逗号形式传参

getName.bind(obj,‘王五11,25,‘上海’)() 或 getName.bind(obj)(‘王五11,25,‘上海’)
函数是否被执行

  
 
  • 1
  • 2

cal和apply是直接调用函数

bind是返回函数本身,如果要执行,必须再后面再加()调用

getName.bind(obj)()

call,apply实现原理

call的实现原理(不用call,自己手动模拟实现一个call的功能)

call是基于函数实现的
给作用的目标对象添加一个临时函数,处理赋值操作
接收参数处理
最后再删除这个临时函数
实例化对象=new 构造函数() //其中构造函数也称为类,一个类可以生成多个实例化对象

var f1=new Function() // 其中的构造函数中this===f1 永远相等
var p1=new Person() //其中的构造函数中this===p1 永远相等
//call模拟实现原理代码:
Function.prototype.call2 = function (context) {
    //目标对象
    context = context || window;

    //this===实例化的函数,函数本质上也是对象

    //给context添加一个临时函数
    context.fn = this;

    //接收参数处理  arguments
    console.log('arguments:',arguments)
    var args = [];
    for (var i = 1; i < arguments.length; i++) {

       // ["arguments[0]", "arguments[1]", "arguments[2]"]
        args.push('arguments['+i+']')
       // args.push(arguments[i])
    }

     //传参执行context.fn()函数
     eval('context.fn(' + args + ')')
    
    
    //删除临时函数
    delete context.fn

    
}


  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38

apply实现原理


Function.prototype.apply2 = function (context,arr) {
//目标对象
context = context || window;
//this===实例化的函数,函数本质上也是对象

//给context添加一个临时函数
context.fn = this;

if (!arr) {
    context.fn()
} else {
    //接收参数处理  arguments
    var args = [];
    for (var i = 0; i < arr.length; i++) {

    // ["arguments[0]", "arguments[1]", "arguments[2]"]
        args.push('arr['+i+']')
    // args.push(arguments[i])
    }

    //传参执行context.fn()函数
    eval('context.fn(' + args + ')')


 }

//删除临时函数
delete context.fn
}


  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31

bind实现原理

var obj = {
    init: 1,
    add: function(a, b) {
        return a + b + this.init;
    }
}
obj.add(1, 2); // 4
 
var plus = obj.add;
plus(3, 4); // NaN,因为 this.init 不存在,这里的 this 指向 window/global
 
plus.call(obj, 3, 4) // 8
plus.apply(obj, [3, 4]); // 8, apply 和 call 的区别就是第二个参数为数组
plus.bind(obj, 3, 4); // 返回一个函数,这里就是 bind 和 call/apply 的区别之一,bind 的时候不会立即执行


  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15

总结

就是简单的使用 bind 来改变 this 指向,和 call/apply 的区别,有一个延迟执行的作用

二、new的实现原理

new的特点

new 一个构造函数,会自动reutrn一个实例化对象
new完的实例化对象____proto___自动指向构造函数的prototype
new构造函数传参自动赋值给当前实例化对象

三、防抖和节流

防抖概念

在固定的时间内没有触发事件,会在固定时间结束后触发,如果固定时间内触发事件了,会在延长固定时间再触发

防抖主要利用定时器实现

//用定时器实现防抖
function debounce(func,wait) {
    var timer=null;
    return function() {
    //保存当前调用的dom对象
     var _this=this;
     //保存事件对象
     var args=arguments;
     clearTimeout(timer)
     timer=setTimeout(function() {
         func.apply(_this,args)
     },wait)
    }

}


  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16

节流概念:

无论在固定时间内是否有事件触发,都会按照固定时间规律触发

具体实现有两种方法

第一种:时间戳

//时间戳版本实现节流
function throttle(func,wait) {
    //定义初始时间
    var oldTime=0;

    return function() {
        var _this=this;
        var args=arguments;

        //当前时间戳
        var newTime=+new Date();

        //判断用当前时间减去旧的时间,如果大于wait指定的时间就会触发
        if(newTime-oldTime>wait) {
            //执行触发的函数
            func.apply(_this,args)
            //将旧时间更新
            oldTime=newTime;
        }

    }


  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22

第二种:定时器

//时间戳版本实现节流
function throttle(func,wait) {
    var timer=null;

    return function() {
        var _this=this;
        var args=arguments;
       if(!timer) {
            timer=setTimeout(function() {
                timer=null;
                func.apply(_this,args)
            },wait)
       }
    }
}


  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16

当然如果以上都不精通可以用目前市面主流工具函数库:lodash已经提供了全面的工具方法

详情请参考lodash网站:https://www.lodashjs.com/.

文章来源: jiangwenxin.blog.csdn.net,作者:前端江太公,版权归原作者所有,如需转载,请联系作者。

原文链接:jiangwenxin.blog.csdn.net/article/details/108331679

【版权声明】本文为华为云社区用户转载文章,如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。