手写实现函数方法之 call、apply、bind、节流与防抖

本文详细介绍了JavaScript中call、apply、bind三个函数方法的实现原理及应用实例,同时探讨了函数节流和防抖两种优化技术的实现和使用场景。通过示例代码展示了如何手动实现这些功能,帮助读者深入理解JavaScript函数的高级用法。
摘要由CSDN通过智能技术生成
一、call 方法
  1. call,语法为 call(fn, obj, ...args),功能为执行 fn,使 thisobj,并将后面的 n 个参数传给 fn,等同于函数对象的 call 方法。
  2. call 的实现,代码如下所示:

export function call (Fn, obj, ...args) {
  // 判断
  if (obj === undefined || obj === null) {
    obj = globalThis; // 全局对象
  }
  // 为 obj 添加临时的方法
  obj.temp = Fn;
  // 调用 temp 方法
  let result = obj.temp(...args);
  // 删除 temp 方法
  delete obj.temp;
  // 返回执行结果
  return result;
}

  1. 手写函数 call 的应用,代码如下所示:
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>call 方法</title>
  <script src="../../src/function/call.js"></script>
</head>
<body>
  <script>
    // 声明一个函数
    function add (a, b) {
      console.log(this);
      return a + b + this.c;
    }
    // 声明一个对象
    let obj = {
      c: 100
    }
    // 添加全局属性
    window.c = 200;

    // 执行 call 函数
    console.log(call(add, obj, 10, 20));
    console.log(call(add, null, 30, 40));
  </script>
</body>
</html>
二、apply 方法
  1. apply,语法为 apply(fn, obj, args),功能为执行 fn,使 thisobj,并将 args 数组中的元素传给 fn,等同于函数对象的 apply 方法。
  2. apply 的实现,代码如下所示:

export function apply (Fn, obj, args) {
  // 判断
  if (obj === undefined || obj === null) {
    obj = globalThis;
  }
  // 为 obj 添加临时的方法
  obj.temp = Fn;
  // 执行方法
  let result = obj.temp(...args);
  // 删除临时属性
  delete obj.temp;
  // 返回结果
  return result;
}

  1. 手写函数 apply 的应用,代码如下所示:
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>apply 方法</title>
  <script src="./../../src/function/apply.js"></script>
</head>
<body>
  <script>
    // 声明一个函数
    function add (a, b) {
      console.log(this);
      return a + b + this.c;
    }
    // 声明一个对象
    let obj = {
      c: 521
    };
    // 添加全局属性
    window.c = 1314;

    // 执行 apply 函数
    console.log(apply(add, obj, [10, 20]));
    console.log(apply(add, null, [30, 40]));
    
    console.log(obj);
  </script>
</body>
</html>
三、bind 方法
  1. bind,语法为 bind(fn, obj, ...args),功能为 给 fn 绑定 thisobj,并指定参数为后面的 n 个参数,等同于函数对象的 bind 方法。
  2. bind 的实现,代码如下所示:

import { call } from './call';

export function bind(Fn, obj, ...args) {
  // 返回一个新的函数
  return function (...args2) {
    // 执行 call 函数
    return call(Fn, obj, ...args, ...args2);
  }
}

  1. 手写函数 bind 的应用,代码如下所示:
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>bind 方法</title>
  <script src="./../../src/function/call.js"></script>
  <script src="./../../src/function/bind.js"></script>
</head>
<body>
  <script>
    // 声明一个函数
    function add(a, b) {
      console.log(this);
      console.log(arguments);
      return a + b + this.c;
    }

    // 声明一个对象
    let obj = {
      c: 521
    }

    // 添加全局属性
    window.c = 1314;

    // 执行函数
    // let fn = bind(add, obj, 10, 20);
    // console.log(fn());

    // let fn2 = bind(add, obj);
    // console.log(fn2(10, 20));

    // let fn3 = add.bind(obj, 10, 20);
    // console.log(fn3(30, 40));


    let fn4 = bind(add, obj, 10, 20);
    console.log(fn4(30, 50));

  </script>
</body>
</html>

四、节流方法
  1. 函数的节流,函数需要频繁触发时,函数执行一次后,只有大于设定的执行周期后才会执行第二次。适合多次事件按时间做平均分配触发。
  2. throttle,语法为 throttle(callback, wait),功能为创建一个节流函数,在 wait 毫秒内最多执行 callback 一次。
  3. throttle 的实现,代码如下所示:

export function throttle (callback, wait) {
  // 定义开始的时间
  let start = 0;
  // 返回结果是一个函数
  return function (e) {
    // 获取当前的时间戳
    let now = Date.now();
    // 判断
    if (now - start >= wait) {
      // 若满足条件,则执行回调函数
      callback.call(this, e);
      // 修改开始的时间
      start = now;
    }
  }
}

  1. 手写函数 throttle 的应用,代码如下所示:
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>函数的节流 throttle</title>
  <script src="../../src/function/throttle.js"></script>
  <style>
    body {
      height: 2000px;
      background: linear-gradient(#125, #eae);
    }
  </style>
</head>
<body>
  <script>
    // 绑定滚动事件
    // window.addEventListener('scroll', function(){
    //   console.log(Date.now());
    // });

    window.addEventListener('scroll', throttle(function(e){
      // console.log(Date.now());
      console.log(e);
    }, 500));
  </script>
</body>
</html>

五、防抖方法
  1. debounce,语法为 debounce(callback, wait),功能为创建一个防抖函数,该函数会从上一次被调用后,延迟 wait 毫秒后调用 callback
  2. debounce 的实现,代码如下所示:

export function debounce (callback, time) {
  // 定时器变量
  let timeId = null;
  // 返回一个函数
  return function (e) {
    // 判断
    if (timeId !== null) {
      // 清空定时器
      clearTimeout(timeId);
    }

    // 启动定时器
    timeId = setTimeout(() => {
      // 执行回调
      callback.call(this, e);
      // 重置定时器变量
      timeId = null;
    }, time);
  }
}

  1. 手写函数 debounce 的应用,代码如下所示:
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>函数的防抖 debounce</title>
  <script src="../../src/function/debounce.js"></script>
</head>
<body>
  <script>
    let input = document.querySelector('input');

    // input.onkeydown = function (e) {
    //   console.log(e.keyCode);
    // };

    input.onkeydown = debounce(function(e){
      console.log(e.keyCode);
    }, 1000);
  </script>
</body>
</html>
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值