JavaScript辨别apply,call,bind 用法与性能

DeepSeek的训练与优化流程 DeepSeek的训练体系不仅追求极致的计算效率,更注重将物理规律、人类知识、安全伦理深度融入训练过程,其"效率-安全-可解释性"三角平衡的设计理念,为行业提供了重要参考范式。 阅读详情

用法

在JavaScript中,我们经常使用apply,call,bind来绑定this的指向,这是this绑定中的硬绑定,即绑定后无法修改。(下面有些代码会涉及this绑定的内容,有关this绑定的内容可以看看我的另一篇博客-->理解掌握JavaScript的this的指向)

首先我们看看下面的代码

function fn(num1, num2, num3) {
    console.log(`a:  ${this.a} sum: ${num1+num2+num3}`);
}

var a = 1;

var obj = {
    a: 2
}

fn(1, 2, 3);//a:  1 sum: 6

fn.call(obj, 1, 2, 3);//a:  2 sum: 6

fn.apply(obj, [1, 2, 3]);//a:  2 sum: 6

fn.bind(obj, 1, 2, 3)();//a:  2 sum: 6

可以看到,我们在方法fn中打印出this.a,且把参数相加打印出来,我们来分析一下上面三个方法的使用和它们的打印结果。

首先先看看全局环境下使用fn方法,因为是在全局中调用的,不是使用new构造的,也并非硬绑定和软绑定,所以是默认绑定,在非严格模式下this.a指向了全局环境下的a,所以fn(1,2,3)最后得到的结果是a:   1 sum:  6。

好,知道了全局环境下直接使用该方法的结果后,我们来看看这三个方法,可以注意

到,三个方法的第一个参数都是对象obj,而最后打印出的结果正式obj.a的值,即是说,在第一个参数上,这三个方法都是一样的,是方法中this要绑定的对象。而后面的参数,是方法的参数,只是形式不一样而已。

我们可以看到,call和bind方法后面的参数都是以逗号分隔开的参数形式,而apply是以数组形式来存放参数的。这就是它们的第一个区别,即参数的传递形式。正是由于apply可以将数组内的成员作为函数的参数传递,所以我们很经常使用apply来把数组内的成员作为参数传递给一个方法。(ES6中提供了扩展运算符用于替代apply的这一用法)

var arr=[1,2,3]

function add(n1,n2,n3){
    console.log(n1,n2,n3);
}

//apply的使用

add.apply(null,arr)//1 2 3

//扩展运算符

add(...arr)//1 2 3

在这里要提出apply的第二个参数实际上不一定要是一个数组,一个带有length的对象也是可以的

function add(n1,n2,n3){
    console.log(n1,n2,n3);
}
add.apply(null,{length:3})
// undefined undefined undefined

//这里实际上可以将第二个参数看为[undefined,undefined,undefined]

接下来继续看三个方法的另一个区别,可以看到,bind后面多了一个括号,即call和apply返回的是函数的调用,而bind返回的是函数,需要再使用括号进行调用。既然如此,那原方法的参数是否可以放在后面的括号里呢,答案是可以的。

fn.bind(obj)(1, 2, 3);//a:  2 sum: 6

fn.bind(obj, 1)(2, 3);//a:  2 sum: 6

fn.bind(obj, 1, 2)(3);//a:  2 sum: 6

这里可以把bind看成是为部分参数提供默认值,利用bind的这一用法,可以很简便地实现函数的柯里化,当然,也可以用来实现thunk。

性能

除了用法之外,还有性能上的区别

这三者的性能排序从高到低(时间消耗从少到多)如下

  1. call
  2. bind
  3. apply

我写了一个demo结合performance来进行测试

<body>
    <button onclick="_call()">call</button>
    <button onclick="_apply()">apply</button>
    <button onclick="_bind()">bind</button>
    <script>
        function fn(a, b) {
            return a + b
        }

        function _call() {
            for (let i = 0; i < 1000000; i++) {
                fn.call(null, 1, 2)
            }
        }

        function _apply() {
            for (let i = 0; i < 1000000; i++) {
                fn.apply(null, [1, 2])
            }
        }

        function _bind() {
            for (let i = 0; i < 1000000; i++) {
                fn.bind(null)(1, 2)
            }
        }
    </script>
</body>

然后在浏览器中,在不同的时间点点击按钮,查看performance中script的时间消耗,结果如图

可以明显看到,apply消耗的时间最多(黄色部分高度最高),接下来我们看到其中具体的时间来比较

这里call和bind消耗的时间差不多,实际上,call和bind在我测试的时候,有时call消耗时间多,有时bind消耗时间多,所以这两个性能上其实区别不大

但是我们可以看到,apply和这两个区别就大了,是十倍的时间,所以在一般情况下,我们尽可能地去使用call和bind,但是有一个问题,如果我们当前的参数在一个数组里,是不是直接用apply比较好呢,在以前,可能是的,但是在ES6之后,有了解构赋值,我们可以将数组的成员解构传参,这里我们修改一下_call函数,使用解构赋值,看性能上是否还是优于apply(因为call和bind差不多,所以我就只测试call做解构赋值处理了),修改函数如下

function _call() {
    for (let i = 0; i < 1000000; i++) {
        fn.call(null, ...[1, 2])
    }
}

可以看到,时间的消耗比apply多,所以如果我们需要传入数组,还是以apply会比较好

 

总的来说,三个方法的区别就有三个

1.第一个参数后面的参数的形式不同,call和bind后面是逗号分隔的参数形式,apply后面是数组形式

2.返回的内容不同,call和apply返回函数调用,bind返回函数

3.性能上的区别,按各自用法call和bind的性能比apply好,但是结合解构赋值,apply性能更好

理解这三个方法的区别并在硬绑定时合理使用,会有很大的便利性。

用OpenCV+ROS实现焊接机器人智能纠偏:线激光视觉的算法调参全流程 本文详细介绍了基于OpenCV和ROS的焊接机器人智能纠偏系统全流程。通过线激光视觉系统实时感知焊缝,重点解析了抗干扰图像预处理、改进的Steger算法提取激光条纹中心线,以及从2D像素到机器人基坐标系的完整坐标变换。该系统为应对焊接飞溅、弧光等复杂工况,实现高精度实时路径纠偏提供了从算法优化到工程集成的完整解决方案。 阅读详情

相关推荐

Ubuntu 22.04 上 Mezzanine CMS 完整安装指南

CMS(内容管理系统)是构建博客、企业官网等静态与动态内容混合站点的核心技术栈;Django 作为 Python 生态中最成熟的 Web 框架,凭借其 ORM、Admin 和安全机制,成为 CMS 开发的首选基础。Mezzanine 是基于 Django 的轻量级 CMS,以开箱即用、零配置多语言和内置 SEO 工具为特色,特别适合中小项目快速落地。在 Ubuntu 这类强调稳定性的服务器操作系统上部署时,关键挑战并非代码逻辑,而是系统层依赖协同——如 Python 版本锁定、SQLite FTS5 支持、

weixin_33508411的博客 304

call和apply性能对比

apply call 基本概念 稍有一些javascript基础的人应该对这两个函数都不会陌生,这里简单过一下基本概念。这两个方法一般都是用来调用一个函数时改变其内部this指向,换句话说:劫持一个对象的方法,继承另外一个对象的属性并调用。语法上两者唯一的不同就是传参形式: Function.apply(obj,args)方法能接收两个参数: obj:这个对象将代替Function类里thi...

包磊磊的博客 1973

ContextCapture导入点云进行重建

ContextCapture导入点云进行重建

天桥飞熊的博客 1万+

Js中的apply、call和bind方法的区别

Js中的apply、call和bind方法的区别

He_9a9的博客 886

ubuntu18.04安装Nvidia显卡驱动后黑屏及网络、蓝牙驱动消失的解决方案

ubuntu18.04安装Nvidia显卡驱动后黑屏及网络、蓝牙驱动消失的解决方案

weixin_40735291的博客 6618

用 CDS 作为 Referenced Data Source 开发 SAP Gateway OData 服务,一条更轻的 SEGW 路线

本文介绍了SAP Gateway项目中从传统手工建模到基于CDS View的现代化开发方式转变。主要内容包括: 传统方式需要在SEGW中手动创建Entity Type、Entity Set等元素,并在DPC_EXT中编写大量查询逻辑,存在模型层和业务逻辑重复表达的问题。 7.50版本后,SAP Gateway与ABAP CDS深度集成,可通过SEGW直接引用CDS View作为数据源,自动生成数据模型和SADL读取逻辑,支持完整的OData查询功能。 最佳实践建议通过Consumption View而非直接

2007 年 ~ 2025 年,深耕 SAP 技术 18 年 706

call、apply、bind哪个性能更好

call() 方法调用一个函数, 其具有一个指定的 this值和分别地提供的参数(参数的列表)。apply()方法调用一个函数, 其具有一个指定的 this 值,以及作为一个数组(或类似数组的对象)提供的参数。bind() 函数会创建一个新函数(称为绑定函数),新函数与被调函数(绑定函数的目标函数)具有相同的函数体(在 ECMAScript 5 规范中内置的call属性)。call的性能要比apply好一些,尤其是传递给函数的参数超过3个时所以后期开发的时候,可以使用call多一些。

subsistent的博客 424

WorkBuddy 连接百度网盘:能查能上传,但别指望 AI 帮你下载

本文介绍了如何通过WorkBuddy连接百度网盘实现文件管理功能。首先需要在百度开放平台创建应用并获取AppKey等凭证,然后通过拼接授权URL获取Access Token并填入WorkBuddy。实际测试表明,该连接器支持查看目录结构、搜索文件及上传文档,但无法实现文件下载和创建分享链接,原因是百度网盘MCP Server未提供相关接口。使用前需明确功能限制,该方案适合需要远程查阅网盘内容但不涉及下载的场景。

u011186532的专栏 1926

js的call比apply性能好

<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title></title> </head> <body> <script> //apply和call都可以改变this的指向,返回值就是函数的返回值 ...

Ych_cxy的博客 368

Sigrity SPEED2000 TDR TDT Simulation模式如何进行时域阻抗仿真分析操作指导-差分信号

Sigrity SPEED2000 TDR TDT Simulation模式如何进行时域阻抗仿真分析操作指导-单端信号详细介绍了单端信号如何进行TDR仿真分析,下面介绍如何对差分信号进行TDR分析,还是以下图为例进行分析。Impedance是时域阻抗曲线,也是最主要的观测指标,注意:impedance曲线的时间刻度不是延时,延时=时间刻度/2,因为TDR测量的是用一来一回的原理去测量的。Use Lossy peeling 默认不勾选,勾选的话代表同时仿真无损和有损方案,不勾选代表仅仿真有损方案。

weixin_54787054的博客 857

【人工智能】国产开源大模型聊天 AquilaChat 快速开始上手实战&效果评测

Aquila语言大模型在技术上继承了GPT-3、LLaMA等的架构设计优点,替换了一批更高效的底层算子实现、重新设计实现了中英双语的tokenizer,升级了BMTrain并行训练方法,在Aquila的训练过程中实现了比Magtron+DeepSpeed zero-2将近8倍的训练效率。Aquila语言大模型是在中英文高质量语料基础上从0开始训练的,通过数据质量的控制、多种训练的优化方法,实现在更小的数据集、更短的训练时间,获得比其它开源模型更优的性能。

AI天才研究院 2万+

JavaScript 中的 bind()、apply() 和 call()鲜为人知的区别

大厂技术高级前端Node进阶点击上方程序员成长指北,关注公众号 回复1,加入高级Node交流群每个开发人员都应该充分了解它们的工作原理,并能够辨别它们之间的细微差别。所以你知道,JS 函数是一等公民。这意味着:它们都只是对象值——Function 类的所有实例,具有方法和属性:因此 bind()、apply() 和 call() 是每个 JavaScript 函数都具有的 3 个基本方法...

程序员成长指北 277

软考中级-软件设计师 Python基础

软考中级-软件设计师 Python知识点整理

片言可决讼,半纸能缚龙 3642

JavaScript 中的 bind()、apply() 和 call():鲜为人知的差异

每个开发者都应该充分理解它们的工作原理,并能够辨别它们之间的微妙差异。首先要知道,JavaScript 函数是“一等公民”。这意味着它们都是对象值——所有函数都是 Function 类的实例,拥有方法和属性:因此,bind()、apply() 和 call() 是每个 JavaScript 函数都具备的三个基本方法。bind()你还记得 React 的早期痛苦时代吗?当时我们仍在使用类组件,并且事...

粉丝们务必加入微信粉丝群 883

数学建模模型总结

这是本人在两年内准备参加数学建模竞赛搜集到的模型资料,已经经过了本人的筛选和整理,希望能够对准备参加数学建模竞赛的学弟学妹们提供一些帮助!

ET2012新版免狗免安装绿色软件

ET2012新版免狗免安祖昂绿色软件。,新界面,新视觉,

前端知识点---this的使用方法详解(Javascript)

在JavaScript中,this 是一个非常重要但是呢 也让人难搞明白的关键字。 **它的值不是在编写代码时静态确定的,而是在代码运行时动态绑定的。**这非常重要下面讲一下它 .在全局作用域中(即不在任何函数中),this 通常指向全局对象:在浏览器中,this 指向 Window 对象。 在Node.js环境中,this 指向 global 对象。 例子二 在严格模式下: 2.2 构造函数调用 当一个函数用作构造函数(通过 new 关键字调用 new关键字创建一个新的对象实例,并将该对象与构造函数绑

2302_80171619的博客 3422

Outlook Express 6 (OE6) for Win7/Win8/Win10

英文版 Outlook Express6.0, 兼容Win7/Win10/WinXP,解压就可用。

JS中的this到底指的是谁?如何辨别?

this: 当前方法执行的主体(谁执行的这个方法,那么this就是谁,所以this和当前方法在哪创建的或者在哪执行都没有必然的关系) 第一:给当前元素的某个事件绑定方法,当事件触发方法执行的时候,方法中的this 是当前操作元素对象 oBox.onclick = fucntion () { // => this 指的是oBox } 第二:普通函数执行,函数中的 this 取决于执行的主体,谁执行的, this 就是谁(执行主体:非严格模式下,方法执行,看方法名前面是否有 点 ,有的话 点 前.

weixin_45757499的博客 566

ssm框架搭建

这个是一个在idea上成功跑起来的ssm框架项目,保存在这里方便以后使用直接下载

JavaScript中的this

直接调用 作为某个对象的方法进行调用 构造函数调用 使用call或apply,以及bind 方法(在ES6中出现的) 指定this所指向的对象 this,英语语法中是一个指示代词,表示指代某些事物。于是在JavaScript中,它其实也是指代了某种东西,一般来说,它指代的都是某个特定的对象。那它指代了什么对象呢? 简单来说,this指代什么,要看包含this的那个函数是如...

下一个自己是你的梦想中的样子 366

js重难点

文章目录var,const,let引用类型执行环境(execution context)基本引用类型stringnumber集合引用类型Array迭代器生成器对象对象解构原型原型链类代理函数基本方法this`apply,call,bind`闭包Promise未完待续 var,const,let 对于var声明的变量,变量声明会提升,即可以理解有个预处理,把整个js代码的var声明的变量首先处理,所以var声明的变量可以重复声明 let声明的变量具有块级作用域,不会发生变量声明提升,所以不可以重复声明,但是

weixin_44876333的博客 801

05 【函数(上)】

05 【函数(上)】

DSelegent的博客 301

5种this的指向

5种this的指向 function say(){ console.log(this) } 1.window say() 2.调用的对象 document.onclick=say 3.构造函数 new say() 4.window 5.window

bobringtheboys的博客 173

高级前端软件工程师知识整理之基础篇(三)

11.介绍一下sessionStorage 、localStorage 和 cookie 之间的区别?cookie和token作为验证手段又有什么区别? sessionStorage 、localStorage 和 cookie都保存在浏览器端,它们的区别是: sessionStorage:作为临时数据存储,在不同的浏览器窗口里并不共享,当关闭浏览器后将会被自动删除。 localStor...

@黄小泽的个人博客 1413

this指向问题

在开发过程中,总是会遇到this指向出现问题的情况,只知道如何解决,但是其中的原理一直不是很了解,有点不求甚解了,今天有幸看见一篇关于this文章,受益颇多。做了一下简单的总结。

low666的博客 202

JavaScript中this指向

大多数的this指向我还是能辨别,但是偶尔遇到特殊的情况我还是会懵圈儿,所以整理整理。首先,最为常见的this ,全局情况下(与严格非严格模式无关):// 浏览器中的this console.log(this); // 输出window对象// 在NodeJS中的this对象 console.log(this); // 输出一个空对象:{}在函数中,this 的指向又有些不同:function t

qq_21916259的博客 254

前端入门12-JavaScript语法之函数

声明 本系列文章内容全部梳理自以下几个来源: 《JavaScript权威指南》 MDN web docs Github:smyhvae/web Github:goddyZhao/Translation/JavaScript 作为一个前端小白,入门跟着这几个来源学习,感谢作者的分享,在其基础上,通过自己的理解,梳理出的知识点,或许有遗漏,或许有些理解是错误的,如有发现,欢迎指点下。 PS:梳理的...

weixin_30284355的博客 115

JS中【bind】详解以及与【apply】和【call】的区别

bind方法是 JavaScript 中非常强大且常用的工具,它能够灵活地绑定函数的this值,并且可以预置参数来实现函数柯里化。在了解bind的工作原理和应用场景后,你可以更好地控制函数的执行上下文和参数传递,使代码更加灵活和可维护。

2301_79858914的博客 4005

GreenGrapes 开源项目指南

GreenGrapes 开源项目指南 项目介绍 GreenGrapes 是一个虚构的开源项目,灵感来源于绿葡萄丰富的健康益处,以此命名象征着该项目旨在带来软件界的“健康”解决方案。尽管实际链接未提供,我们假设它是一款关注于数据处理和优化的工具,特别适合那些寻求高性能和易用性的开发者。它集成了先进的算法和库,使得数据管理和分析变得更加高效。 项目快速启动 要快速启动 GreenGrapes 项目,确...

gitblog_00091的博客 396
上一篇: 理解掌握JavaScript的this的指向
下一篇: 常见的http状态码
前端小黑
博客等级 码龄9年 148粉丝 222原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值