深入理解JavaScript - JavaScript中call、apply、bind方法

一、call() / apply()

JavaScript中的函数是对象,与其他JavaScript对象一样,JavaScript函数也有方法。其中有两个自带的方法 – call和apply,可以利用这两个方法来间接调用某个函数。

通过一个简单的例子体会一下call和apply的用法:

function f(){console.log(this.name)
}
let obj = {name:"obj"}
f.call(obj) // => obj :调用函数f,并指定this值为obj对象
f.apply(obj) // => obj :调用函数f,并指定this值为obj对象

上面的代码类似于下面的程序:

let obj = {name:"obj"}
obj.f =  f;// 在对象上定义一个属性指向f函数对象
obj.f();
delete obj.f;

从第一段程序看,call和apply没什么区别。事实上两个方法的区别确实很小,只在传递参数形式上有去区别。

两个方法,只有参数形式的区别

apply的参数要求是数组或类数组对象
下面是一段给apply、call方法传递多个参数的程序,看看它们之间的区别:

function f(p1, p2) {console.log(this.name, p1, p2)
}
// f.apply(obj,1,2) // => 报错:Uncaught TypeError: ...called on non-object
f.apply(obj, [1, 2]);//obj 1 2 : 传递给函数的参数需要采用数组或类数组的形式
let arrlike = { 0: "1", 1: "2", length: 2 };
f.apply(obj, arrlike);// => obj 1 2 : 传递给函数的参数需要采用数组或类数组的形式let obj = { name: "obj" }
f.call(obj, 1, 2) // => obj 1 2 :调用函数f,并指定this值为obj对象,传递两个实参给f函数

⚠️ apply传递参数需要采用数组或类数组的形式,否则报错

apply使用场景

ES6前替代扩展操作符 – 将参数数组转换为参数列表

let max = Math.max(2,3,5,7,0);
console.log(max);// 7max = Math.max([2,3,5,7,0]);
console.log(max);// NaNmax = Math.max(...[2,3,5,7,0]);
console.log(max);// 7max = Math.max.apply(Math,[2,3,5,7,0]);
console.log(max);// 7

箭头函数问题

⚠️ 箭头函数调用call/apply方法,第一个参数会被忽略(因为箭头函数的this值在定义时绑定)。

var name = "window"
let arrow_fun = (v) => {console.log(this.name,v);// window 1
}
let normal_fun = function(v){console.log(this.name,v);// window 1
}
var obj = {name: "obj"
}
arrow_fun.call(obj, 1, 3); // window 1:箭头函数中第一个参数(obj)被忽略,实参3无参数接收被忽略
normal_fun.call(obj, 1, 3);// obj 1:实参3没有参数接收被忽略

二、bind方法

( bind()方法的主要目的是把函数绑定到对象 . 这句话会让人误以为给对象添加了一个新方法)

其实,bind方法是利用现有函数,创建并返回一个新的函数,同时为其绑定了一个对象为this。
(apply和call是绑定this并直接调用)

function f(y) {return (this.x + y);
}
let o1 = { x: 1 };
let fbo1 = f.bind(o1);//bind方法是利用现有f函数,创建并返回一个新的函数,同时绑定了o1为新函数的this
// o1.f(); // 报错: Uncaught TypeError: o.f is not a function
console.log(fbo1(2)); // => 3let o2 = { x: 90, fbo1 };
console.log(o2.fbo1(10)); // => 11: fbo函数仍然与o绑定.

⚠️ o1.f() 报错 ,bind并没有给对象添加了一个新方法!

柯里化

bind方法不但可以绑定对象为新函数的this,还能为函数绑定参数

function f(y) {return (this.x + y);
}
let o1 = { x: 1 };
let fbo1 = f.bind(o1,9);//bind方法是利用现有f函数,创建并返回一个新的函数
//同时绑定了o1为新函数的this;
//还绑定的新函数的第一个参数的值一直为9
console.log(fbo1(2)); // => 10 函数的参数已经绑定了9,再传参就无效了

返回的新函数上绑定o1为this值,同时绑定了一个参数值9,见下图
在这里插入图片描述
从图中可以看出,绑定的参数是以数组的形式绑定的。

三、总结

// call/apply绑定对象为this,并直接执行
函数.call(绑定的对象,参数1...参数n);
函数.apply(绑定的对象,[参数1...参数n]); // 仅绑定对象为this并返回新函数,并不执行
函数.bind(绑定的对象);

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

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

相关文章

嵌入式学习54-ARM3

S3c2440中断控制器 内部外设: DMA :(直接内存存取) Direct Memor…

基于docker的开发者集成环境

docker-compose一键部署开发者环境。 常见的中间件:nginx, mysql, redis, mongo, rabbitmq, nacos, rocketmq, zookeeper等。 GIthub项目地址 1. 下载项目:git clone https://github.com/xhga/docker-develop-env.git 2. 进入文件夹:cd d…

服务器测试之intel E8102CQDA2

这个卡是个双口100G双芯片的卡,QSFP28 单口速率100G,双口200G 1.BIOS下pcie带宽设置 服务器BIOS下支持设置PCIE link width 设置x8x8,否则只能显示一个网口,如下图 E810-2CQDA2需要BIOS下设置该卡槽位pcie slot link width 设置x8…

Paddle实现人脸对比(二)

我之前发过一篇基于孪生网络的人脸对比的文章,这篇文章也到了百度的推荐位置: 但是,效果并不是很好。经过大量的搜索,我发现了一种新的方法,可以非常好的实现人脸对比。 原理分析 我们先训练一个普通的人脸分类模型&…

OpenCV4.10使用形态运算提取水平线和垂直线

目标 在本教程中,您将学习如何: 应用两个非常常见的形态运算符(即膨胀和侵蚀),并创建自定义内核,以便在水平轴和垂直轴上提取直线。为此,您将使用以下 OpenCV 函数: erode()dilate…

认识异常(2)

❤️❤️前言~🥳🎉🎉🎉 hellohello~,大家好💕💕,这里是E绵绵呀✋✋ ,如果觉得这篇文章还不错的话还请点赞❤️❤️收藏💞 💞 关注💥&a…

python创建word文档并向word中写数据

一、docx库的安装方法 python创建word文档需要用到docx库,安装命令如下: pip install python-docx 注意,安装的是python-docx。 二、使用方法 使用方法有很多,这里只介绍创建文档并向文档中写入数据。 import docxmydocdocx.Do…

基于生成对抗网络在服装领域的发展脉络和应用趋势

文章目录 1、概述2、深度学习图像生成模型2.1、深度信念网络(Deep belief network,DBN)2.2、变分自编码器(Variational auto-encoder,VAE)2.3、生成对抗网络(Generative adversarial networks,GAN) 3、 模型对比分析4、基于多模态转换的服装图…

nexus搭建maven与docker镜像的私有仓库

引言 通过nexus搭建maven与docker镜像的私有仓库,实现jar包与镜像动态更新、共享、存储。 一、nexus部署 通过docker-compose部署nexus name: java services:#############################环境#############################env-nexus:restart: always## 3.58.1image: so…

代码随想录算法训练营第三十七天| LeetCode 738.单调递增的数字、总结

一、LeetCode 738.单调递增的数字 题目链接/文章讲解/视频讲解:https://programmercarl.com/0738.%E5%8D%95%E8%B0%83%E9%80%92%E5%A2%9E%E7%9A%84%E6%95%B0%E5%AD%97.html 状态:已解决 1.思路 如何求得小于等于N的最大单调递增的整数?98&am…

【C语言基础】:编译和链接(计算机中的翻译官)

文章目录 一、翻译环境和运行环境1. 翻译环境1.1 编译1.1.1 预处理1.1.2 编译1.1.3 汇编 1.2 链接 2. 运行环境 一、翻译环境和运行环境 我们在Visual Studio上写的C语言代码其实都是一些文本信息,计算机是不能够直接执行他们的,计算机只能够执行二进制…

第6章 6.4.1 案例一:爬取亚洲各地区的实时时间(MATLAB入门课程)

讲解视频:可以在bilibili搜索《MATLAB教程新手入门篇——数学建模清风主讲》。​ MATLAB教程新手入门篇(数学建模清风主讲,适合零基础同学观看)_哔哩哔哩_bilibili 本案例将引导大家爬取亚洲各地区的实时时间。我们将从下面这个网…

第 128 场 LeetCode 双周赛题解

A 字符串的分数 模拟 class Solution {public:int scoreOfString(string s) {int res 0;for (int i 1; i < s.size(); i) res abs(s[i] - s[i - 1]);return res;} };B 覆盖所有点的最少矩形数目 排序&#xff1a;先按照 x i x_i xi​ 排序&#xff0c;然后顺序遍…

【C++庖丁解牛】底层为红黑树结构的关联式容器--哈希容器(unordered_map和unordered_set)

&#x1f341;你好&#xff0c;我是 RO-BERRY &#x1f4d7; 致力于C、C、数据结构、TCP/IP、数据库等等一系列知识 &#x1f384;感谢你的陪伴与支持 &#xff0c;故事既有了开头&#xff0c;就要画上一个完美的句号&#xff0c;让我们一起加油 目录 1. unordered系列关联式容…

系统架构设计图

首先明确应用架构的定义&#xff0c;从百度百科上即可了解到何为应用架构&#xff1a; 应用架构&#xff08;Application Architecture&#xff09;是描述了IT系统功能和技术实现的内容。应用架构分为以下两个不同的层次&#xff1a; 企业级的应用架构&#xff1a;企业层面的应…

arm工作模式、arm9通用寄存器、异常向量表中irq的异常向量、cpsr中的哪几位是用来设置工作模式以及r13,r14,15别名是什么?有什么作用?

ARM 首先先介绍一下ARM公司。 ARM成立于1990年11月&#xff0c;前身为Acorn计算机公司 主要设计ARM系列RISC处理器内核 授权ARM内核给生产和销售半导体的合作伙伴ARM公司不生产芯片 提供基于ARM架构的开发设计技术软件工具评估版调试工具应用软件总线架构外围设备单元等等CPU中…

【MySQL】MySQL在Centos 7环境安装

目录 准备工作 第一步&#xff1a;卸载不要的环境 第二步&#xff1a;下载官方的mysql 第三步 上传到Linux中 第四步 安装 正式安装 启动 ​编辑 登录 准备工作 第一步&#xff1a;卸载不要的环境 使用root进行安装 如果是普通用户&#xff0c;使用 su - 命令&#…

langchain RunableBranch 分类判断选择不同链

import os from dotenv import load_dotenv from langchain_community.llms import Tongyi load_dotenv(key.env) # 指定加载 env 文件 key os.getenv(DASHSCOPE_API_KEY) # 获得指定环境变量 DASHSCOPE_API_KEY os.environ["DASHSCOPE_API_KEY"] # 获得指定环境…

字符串转换为List<String>时候抛出异常:com.alibaba.fastjson2.JSONException: TODO : s

前言&#xff1a; 一个字符串想要能够转换为 List&#xff0c;其本身必须是具备 List 属性的字符串。 问题现象&#xff1a; 项目中需要对第三方接口返回的字符串转换为 List&#xff0c;就想到了使用 fastjson 来处理。 代码如下&#xff1a; Object obj data.get(SignC…

格式化D盘后C盘内的文件会受影响吗?深度解析

在计算机的日常使用中&#xff0c;磁盘格式化是一个常见的操作&#xff0c;它能帮助我们清除磁盘上的数据&#xff0c;为新的数据腾出空间。然而&#xff0c;当涉及到系统盘和其他存储盘时&#xff0c;许多用户会担心一个问题&#xff1a;如果我格式化了非系统盘&#xff0c;比…