call,apply,bind的使用及原理

news2024/10/9 10:20:10

call,apply,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>Document</title>
  </head>
  <body>
    <script>
      var name = 'tc'

      const obj = {
        name: 'ljr',
        say: function (val, hobby) {
          return this.name + val + hobby
        },
      }

      console.log(obj.say('你好', '喜欢打球')) //ljr你好喜欢打球
      const f = obj.say
      console.log(f('你好', '喜欢打球')) //tc你好喜欢打球
      console.log(f.call(obj, '是美女', '喜欢唱歌')) //ljr是美女喜欢唱歌
      console.log(f.apply(obj, ['是小仙女', '喜欢唱歌'])) //ljr是小仙女喜欢唱歌
      console.log(f.bind(obj, '是宝藏女孩,', '喜欢唱周杰伦的歌')()) //ljr是宝藏女孩,喜欢唱周杰伦的歌
    </script>
  </body>
</html>

三者的区别

call与apply的唯一区别

传给fun的参数写法不同:

  • apply是第2个参数,这个参数是一个数组:传给fun参数都写在数组中。
  • call从第2~n的参数都是传给fun的。

call/apply与bind的区别

执行

  • call/apply改变了函数的this上下文后马上执行该函数
  • bind则是返回改变了上下文后的函数,不执行该函数

返回值:

  • call/apply 返回fun的执行结果
  • bind返回fun的拷贝,并指定了fun的this指向,保存了fun的参数。

原理:

手写 call

Function.prototype.myCall = function(context = globalThis) {
  // 设置 fn 为调用 myCall 的方法
  context.fn = this;

  // 获取剩余参数
  const otherArg = Array.from(arguments).slice(1);

  // 调用这个方法,将剩余参数传递进去
  context.fn(otherArg);

  // 将这个方法的执行结果传给 result
  let result = context.fn();

  // 删除这个变量
  delete context.fn;

  // 返回 result 结果
  return result;
};

this.a = 1;

const fn = function() {
  this.a = 2;
  console.log(this.a);
}

fn.myCall(fn);

手写apply

Function.prototype.myApply = function(context = globalThis, arr) {
  // 设置 fn 为调用 myCall 的方法
  context.fn = this;

  let result;

  // 如果存在参数,则传递进去
  // 将结果返回给 result
  if (arr) {
    result = context.fn(arr);
  } else { // 否则不传
    result = context.fn();
  }

  // 删除这个变量
  delete context.fn;

  // 返回 result 结果
  return result;
};

this.a = 1;

const fn = function() {
  this.a = 2;
  console.log(this.a);
}

fn.myApply(fn);

手写bind

Function.prototype.myBind = function(context = globalThis) {
  // 设置 fn 为调用 myCall 的方法
  const fn = this;

  // 获取该方法剩余参数
  const otherArg = [...arguments].slice(1);

  // 设置返回的一个新方法
  const result = function() {

    // 获取返回方法体的参数
    const resultArg = [...arguments];

    // 如果是通过 new 调用的,绑定 this 为实例对象
    if (this instanceof result) {
      fn.apply(this, otherArg.concat(resultArg));
    } else { // 否则普通函数形式绑定 context
      fn.apply(context, otherArg.concat(resultArg));
    }
  }

  // 绑定原型链
  result.prototype = Object.create(fn.prototype);

  // 返回结果
  return result;
};

this.a = 1;

const fn = function() {
  this.a = 2;
  console.log(this.a);
}

fn.myBind(fn);
fn();

函数的Arguments 对象

arguments 是一个对应于传递给函数的参数的类数组对象。

function fun(a, b, c) {
  console.log(arguments[0]); // 1
  console.log(arguments[1]); // 2
  console.log(arguments[2]); // 3
}
复制代码

arguments 对象不是一个 Array

它类似于 Array,但除了 length 属性和索引元素之外没有任何 Array 属性。

arguments 转为数组:

// ES5
var arg1 = Array.prototype.slice.call(arguments);
var arg2 = [].slice.call(arguments);

// ES6
var arg3 = Array.from(arguments);
var arg4 = [...arguments];
复制代码

在手写 call/bind/apply 过程中,会用到 arguments 来获取方法体的传参,就好比手写 call 过程中,通常我们通过 Array.from(arguments).slice(1) 来获取第二个及后面的参数。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/191082.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

StarRocks市场渗透率跻身Top10!

近日&#xff0c;国内著名的研究咨询机构艾瑞咨询发布了《2022年中国数据库研究报告》&#xff08;以下简称“报告”&#xff09;。报告指出&#xff0c;目前数据库产品的国内渗透率达到前所未有的高度&#xff0c;且头部效应明显。其中&#xff0c;StarRocks以“极速统一”的性…

java常用类:日期类Date,Calender和LocalDateTime

java常用类型: Ineteger等包装类 String类&#xff0c;StringBuffer类和StringBuilder类 Math类及常用方法 System类及常用方法 Arrays类及常用方法 BigInteger类和BigDecimal类及常用方法 日期类Date类,Calender类和LocalDateTime类 文章目录引言日期类Date(第一代)时间戳转字…

缓存更新策略分析

缓存常用于读多写少的场景&#xff0c;用于缓存结果数据&#xff0c;降低响应时间&#xff0c;提高服务性能。通常缓存与数据库一起使用&#xff0c;数据库负责持久化&#xff0c;缓存负责高性能。数据库无法同时满足持久化与高性能&#xff0c;所以引入缓存解决高性能问题。缓…

SwiftUI 文本框TextField添加清除按钮

这里写自定义目录标题前言/背景实现参考前言/背景 使用SwiftUI框架&#xff0c;希望在文本框TextField控件中输入内容后显示一个清除按钮,可以清空内容,像这样&#xff1a; UIKit 框架的 UITextField可以配置clearButtonMode,但是SwiftUI框架里的TextField没有这个&#xff…

javaScript常用语法

一、数据类型1. 原始数据类型(7个)number, string, boolean, undefined, null, symbol, bigint1.1 number包括以下三种浮点和整型数字(如3.1416926和3)NaN(not a number)不是数字infinity超出js数字范围的数值2. 引用数据类型(3个)object, array, function2.1 特殊类型RegExp, …

MySQL Performance Schema知识点

MySQL Performance Schema知识点 程序插桩&#xff08;instrument&#xff09;。程序插桩在MySQL代码中插入探测代码&#xff0c;以获取我们想了解的信息。 消费者表&#xff08;consumer&#xff09;&#xff0c;指的是存储关于程序插桩代码信息的表。如果我们为查询模块添加…

基于Springboot搭建java项目(二十六)——创建Vue前端项目

创建Vue前端项目 一、创建Vue前端项目 1、安装 Vue CLI 1.1、下载Node.js 因为需要使用 npm 安装 Vue CLI&#xff0c;而 npm 是集成在 Node.js 中的&#xff0c;所以第一步我们需要安装 Node.js&#xff0c;访问官网 https://nodejs.org/en/&#xff0c;首页即可下载。 下…

day26|455.分发饼干、376. 摆动序列、53. 最大子序和。进军贪心

455.分发饼干 假设你是一位很棒的家长&#xff0c;想要给你的孩子们一些小饼干。但是&#xff0c;每个孩子最多只能给一块饼干。 对每个孩子 i&#xff0c;都有一个胃口值 g[i]&#xff0c;这是能让孩子们满足胃口的饼干的最小尺寸&#xff1b;并且每块饼干 j&#xff0c;都有…

Python | 数据类型之元组和字典

知识目录一、元组(tuple)1.1 元组的创建1.2 访问和修改元组1.3 内置函数二、字典(dict)2.1 字典的创建2.2 访问和修改字典2.3 字典键的特性2.4 函数与方法一、元组(tuple) Python 的元组与列表类似&#xff0c;不同之处在于元组的元素不能修改。 元组使用小括号&#xff0c;列…

kubernetes-dashboard 实现 http 访问以及免 token 登录

文章目录[toc]下载官方 yaml 文件修改 yaml 文件修改 service 端口修改 clusterrolebinding修改 deployment 内容修改探针检测修改镜像拉取策略修改容器端口关闭 token 登录增加 ingress完整版 yaml下载官方 yaml 文件 最后有完整版的 yaml 文件&#xff0c;不想看细节的话&am…

苹果中的这些小技巧,你知道吗

技巧一&#xff1a;iPhone镜像 觉得手机屏幕太小看电影玩游戏不爽怎么办&#xff1f;投屏功能帮我们解决了问题&#xff0c;使用方法也很简单。打开控制中心&#xff0c;点击投屏&#xff0c;选择设备&#xff0c;连接投屏。这里需要注意的是&#xff0c;手机和连接的设备必须在…

【MIKE水动力】MIKE11基本原理(上)

Mike11软件包由水动力、对流&#xff5e;扩散、水质、降雨&#xff5e;径流、洪水预报等模块组成&#xff0c;核心模块为水动力模块。Mike11水动力模块采用6点Abbott&#xff5e;Ionescu有限差分格式对圣维南方程组求解。 一、圣维南方程组 1、基本要素与假设条件 Mike11模型…

开源流程引擎activiti、flowable、camunda选哪个好?

市场上比较有名的开源流程引擎有osworkflow、jbpm、activiti、flowable、camunda。其中&#xff1a;Jbpm4、Activiti、Flowable、camunda四个框架同宗同源&#xff0c;祖先都是Jbpm4&#xff0c;开发者只要用过其中一个框架&#xff0c;基本上就会用其它三个。低代码平台、办公…

IO流概念、FileWriter类及FileReader类详解

目录 IO流概述和分类 ​编辑FileWriter写数据 FileWriter写数据的方法 FileWriter写数据常见问题 FileReader读数据 IO流概述和分类 IO流用来处理设备之间的数据传输–文件复制,上传文件和下载文件 IO流分类–输出流——FileWriter –输入流——FileReader 图式详解&am…

< 每日算法 - Javascript解析: 交通枢纽 >

每日算法 - JavaScript解析&#xff1a;交通枢纽一、任务描述&#xff1a;》 示例一&#xff1a;》示例二二、题意解析拓展知识三、解决方案&#xff1a;往期内容 &#x1f4a8;一、任务描述&#xff1a; 为了缓解「力扣嘉年华」期间的人流压力&#xff0c;组委会在活动期间开…

谷歌优化排名怎么做?Google SEO怎么优化?

本文主要分享关于Google自然排名优化中的一些方法和技巧&#xff0c;让你更快的做好谷歌排名。 本文由光算创作&#xff0c;有可能会被修改和剽窃&#xff0c;我们佛系对待这种行为吧。 谷歌优化排名怎么做&#xff1f;Google SEO怎么优化&#xff1f; 答案是&#xff1a;创…

CMOS器件与TTL器件CMOS电平与TTL电平

常用的数字芯片&#xff0c;按制造工艺主要分为TTL器件和CMOS器件。TTL器件是指其内部主要逻辑单元为双极性晶体管&#xff0c;CMOS器件是指其内部的主要逻辑单元为MOS管。现在绝大部分数字芯片使用的工艺都是CMOS工艺&#xff0c;在一些比较老的74系列芯片中还使用的是TTL工艺…

51单片机最强模块化封装(1)

文章目录前言一、sys文件创建和路径添加1.创建文件夹添加文件夹路径二、sys文件编写1.sys.h2.sys.c三、模块化的测试总结前言 今天将为大家讲解51单片机的模块化封装&#xff0c;为什么要讲这个模块化封装呢&#xff1f;模块化封装将提高我们代码的可移植性和可复用性&#xf…

力扣刷题记录——1002. 查找共用字符、905. 按奇偶排序数组、 977. 有序数组的平方

本专栏主要记录力扣的刷题记录&#xff0c;备战蓝桥杯&#xff0c;供复盘和优化算法使用&#xff0c;也希望给大家带来帮助&#xff0c;博主是算法小白&#xff0c;希望各位大佬不要见笑&#xff0c;今天要分享的是——《力扣刷题记录——1002. 查找共用字符、905. 按奇偶排序数…

服务器被ddos攻击的处置策略

如果您的服务器遭到了DDoS攻击&#xff0c;以下是一些可以采取的措施&#xff1a;使用防火墙和安全组进行限制&#xff1a;限制服务器的流量以防止进一步的攻击。升级服务器资源&#xff1a;为了应对更高的流量&#xff0c;可以升级服务器的内存&#xff0c;处理器等资源。安装…