JavaScript中的call、apply、bind深入理解

深入理解 JavaScript 中的 call、apply 和 bind call、apply 和 bind 是 JavaScript 中非常重要的方法,它们通过显式地改变 this 的指向,提供了更灵活的函数调用方式。理解它们的区别和实现原理,可以帮助我们更好地掌握 JavaScript 的函数执行机制,并在实际开发中灵活运用。 阅读详情

一、函数的三种角色


首先要先了解在函数本身会有一些自己的属性,比如:

  • length:形参的个数;
  • name:函数名;
  • prototype:类的原型,在原型上定义的方法都是当前这个类的实例的公有方法;
  • __proto__:把函数当做一个普通对象,指向Function这个类的原型

函数在整个JavaScript中是最复杂也是最重要的知识,对于一个函数来说,会存在多种角色:

function Fn() {
    var num = 500;
    this.x = 100;
}
Fn.prototype.getX = function () {
    console.log(this.x);
}
Fn.aaa = 1000;

var f = new Fn;

f.num // undefined
f.aaa // undefined
var res = Fn(); // res是undefined  Fn中的this是window
  • 角色一:普通函数,对于Fn而言,它本身是一个普通的函数,执行的时候会形成私有的作用域,然后进行形参赋值、预解析、代码执行、执行完成后内存销毁;

  • 角色二:类,它有自己的实例,f就是Fn作为类而产生的一个实例,也有一个叫做prototype的属性是自己的原型,它的实例都可以指向自己的原型;

  • 角色三:普通对象,Fn和 var obj = {} 中的obj一样,就是一个普通的对象(所有的函数都是Function的实例),它作为对象可以有一些自己的私有属性,也可以通过__proto__找到Function.prototype;

函数的以上三种角色,可能大多数同学对于角色一和角色二都是没有任何疑问的,不过对于角色三可能会稍有疑惑,那么画张图来理解下吧:

函数作为普通对象.png

二、call深入


2.1、call的基本使用
var ary = [12, 23, 34];
ary.slice();

以上两行简单的代码的执行过程为:ary这个实例通过原型链的查找机制找到Array.prototype上的slice方法,让找到的slice方法执行,在执行slice方法的过程中才把ary数组进行了截取。

注意:slice方法执行之前有一个在原型上查找的过程(当前实例中没有找到,再根据原型链查找)。

当知道了一个对象调用方法会有一个查找过程之后,我们再看:

var obj = {name:'iceman'};
function fn() {
    console.log(this);
    console.log(this.name);
}
fn(); // this --> window
// obj.fn(); // Uncaught TypeError: obj.fn is not a function
fn.call(obj);

call方法的作用:首先寻找call方法,最后通过原型链在Function的原型中找到call方法,然后让call方法执行,在执行call方法的时候,让fn方法中的this变为第一个参数值obj,最后再把fn这个函数执行。

2.2、call方法原理

模拟Function中内置的call方法,写一个myCall方法,探讨call方法的执行原理

function sum(){
    console.log(this);
}
function fn(){
    console.log(this);
}
var obj = {name:'iceman'};
Function.prototype.myCall = function (context) {
    // myCall方法中的this就是当前我要操作和改变其this关键字的那个函数名

    // 1、让fn中的this关键字变为context的值->obj
    // 让this这个函数中的"this关键字"变为context
    // eval(this.toString().replace("this","obj"));

    // 2、让fn方法在执行
    // this();
};
fn.myCall(obj);// myCall方法中原来的this是fn
sum.myCall(obj);// myCall方法中原来的this是sum

当 fn.myCall(obj); 这行代码执行的时候,根据this的寻找规律,在myCall方法前面有".",那么myCall中的this就是fn。执行myCall的方法,在第一步会将方法体中this换为传入的对象,并且执行原来的this, 注意:是执行原来的this(我在学这一块的时候这里理解了好久),在本例中就是执行fn。

看完以上那段话是不是有些懵逼了呢?哈哈,没事,接下来看下面例子,理解一下。

2.3、call方法经典例子
function fn1() {
    console.log(1);
}
function fn2() {
    console.log(2);
}
2.3.1、输出一
fn1.call(fn2); // 1

首先fn1通过原型链查找机制找到Function.prototype上的call方法,并且让call方法执行,此时call这个方法中的this就是要操作的fn1。在call方法代码执行的过程过程中,首先让fn1中的“this关键字”变为fn2,然后再让fn1这个方法执行。

注意:在执行call方法的时候,fn1中的this的确会变为fn2,但是在fn1的方法体中输出的内容中并没有涉及到任何和this相关的内容,所以还是输出1.

2.3.2、输出二
fn1.call.call(fn2); // 2

首先fn1通过原型链找到Function.prototype上的call方法,然后再让call方法通过原型再找到Function原型上的call(因为call本身的值也是一个函数,所以同样可以让Function.prototype),在第二次找到call的时候再让方法执行,方法中的this是fn1.call,首先让这个方法中的this变为fn2,然后再让fn1.call执行。

这个例子有点绕了,不过一步一步来理解。在最开始的时候,fn1.call.call(fn2) 这行代码的最后一个call中的this是fn1.call,根据前面的理解可以知道 fn1.call 的原理大致为:

Function.prototype.call = function (context) {
    // 改变fn中的this关键字
    // eval(....);
    
    // 让fn方法执行
    this(); // 此时的this就是fn1
};

将上面的代码写为另一种形式:

Function.prototype.call = test1;
function test1 (context) {
    // 改变fn中的this关键字
    // eval(....);
    
    // 让fn方法执行
    this(); // 此时的this就是fn1
};

我们知道,这两种形式的写法的作用是一样的。那么此时可以将 fn1.call.call(fn2) 写成 test1.call(fn2) ,call中的的this就是test1:

Function.prototype.call = function (context) {
    // 改变fn中的this关键字
    // eval(....);
    
    // 让fn方法执行
    this(); // 此时的this就是test1
};

注意:此时call中的的this就是test1。

然后再将call中this替换为fn2,那么test1方法变为:

Function.prototype.call = function (context) {
    // 省略其他代码
    
    fn2(); 
};

所以最后是fn2执行,所以最后输出2。

三、call、apply、bind的区别


首先补充严格模式这个概念,这是ES5中提出的,只要写上:

"use strict"

就是告诉当前浏览器,接下来的JavaScript代码将按照严格模式进行编写。

function fn() {
    console.log(this);
}
fn.call(); // 普通模式下this是window,在严格模式下this是undefined
fn.call(null); // 普通模式下this是window,在严格模式下this是null
fn.call(undefined); // 普通模式下this是window,在严格模式下this是undefined

apply方法和call方法的作用是一模一样的,都是用来改变方法的this关键字,并且把方法执行,而且在严格模式下和非严格模式下,对于第一个参数是null/undefined这种情况规律也是一样的,只是传递函数的的参数的时候有区别。

function fn(num1, num2) {
    console.log(num1 + num2);
    console.log(this);
}
fn.call(obj , 100 , 200);
fn.apply(obj , [100, 200]); 

call在给fn传递参数的时候,是一个个的传递值的,而apply不是一个个传的,而是把要给fn传递的参数值同一个的放在一个数组中进行操作,也相当于一个个的给fn的形参赋值。

bind方法和apply、call稍有不同,bind方法是事先把fn的this改变为我们要想要的结果,并且把对应的参数值准备好,以后要用到了,直接的执行即可,也就是说bind同样可以改变this的指向,但和apply、call不同就是不会马上的执行。

var tempFn = fn.bind(obj, 1, 2);
tempFn();

第一行代码只是改变了fn中的this为obj,并且给fn传递了两个参数值1、2,但是此时并没有把fn这个函数给执行,执行bind会有一个返回值,这个返回值tempFn就是把fn的this改变后的那个结果。

注意:bind这个方法在IE6~8下不兼容。

四、call、apply的应用


4.1、求数组的最大值和最小值

定义一个数组:

var ary = [23, 34, 24, 12, 35, 36, 14, 25];
4.1.1、排序再取值法

首先先给数组进行排序(小--->大),第一个和最后一个就是我们想要的最小值和最大值。

var ary = [23, 34, 24, 12, 35, 36, 14, 25];
ary.sort(function (a, b) {
    return a - b;
});
var min = ary[0];
var max = ary[ary.length - 1];
console.log(min, max);
4.1.2、假设法

假设当前数组中的第一个值是最大值,然后拿这个值和后面的项逐一进行比较,如果后面某一个值比假设的还要打,说明假设错了,我们把假设的值进行替换.....

var max = ary[0], min = ary[0];
for (var i = 1; i < ary.length; i++) {
    var cur = ary[i];
    cur > max ? max = cur : null;
    cur < min ? min = cur : null;
}
console.log(min, max);
4.1.3、Math中的max/min方法实现(通过apply)

直接使用Math.min

var min = Math.min(ary);
console.log(min); // NaN
console.log(Math.min(23, 34, 24, 12, 35, 36, 14, 25));

直接使用Math.min的时候,需要把待比较的那堆数一个个的传递进去,这样才可以得到最后的记过,一下放一个ary数组进去是不可以的。

尝试:使用eval

var max = eval("Math.max(" + ary.toString() + ")");
console.log(max);
var min = eval("Math.min(" + ary.toString() + ")");
console.log(min);

"Math.max(" + ary.toString() + ")" --> "Math.max(23,34,24,12,35,36,14,25)"首先不要管其他的,先把我们最后要执行的代码都变为字符串,然后把数组中的每一项的值分别的拼接到这个字符串中。

eval:把一个字符串变为JavaScript表达式执行
例如:eval("12+23+34+45") // 114

通过apply调用Math中的max/min

var max = Math.max.apply(null, ary); 
var min = Math.min.apply(null, ary);
console.log(min, max);

在非严格模式下,给apply的第一个参数为null的时候,会让max/min中的this指向window,然后将ary的参数一个个传给max/min。

4.2、求平均数

现在模拟一个场景,进行某项比赛,评委打分后,要求去掉一个最高分和最低分,剩下分数求得的平均数即为最后分数。

可能很多同学会想到用,写一个方法,让后接收所有的分数,然后用函数的内置属性arguments,把arguments调用sort方法排序,然后......,但是要注意,arguments并不是真正的数组对象,它只是伪数组集合而已,所以直接调用用arguments调用sort方法是会报错的:

arguments.sort(); // Uncaught TypeError: arguments.sort is not a function

那么这时候可不可以先将arguments转换为一个真正的数组呢,然后再进行操作呢,按照这个思想,我们自己实现一个实现题目要求的业务方法:

function avgFn() {
    // 1、将类数组转换为数组:把arguments克隆一份一模一样的数组出来
    var ary = [];
    for (var i = 0; i < arguments.length; i++) {
        ary[ary.length] = arguments[i];
    }
    
    // 2、给数组排序,去掉开头和结尾,剩下的求平均数
    ary.sort(function (a, b) {
        return a - b;
    });
    ary.shift();
    ary.pop();
    return (eval(ary.join('+')) / ary.length).toFixed(2);
}
var res = avgFn(9.8, 9.7, 10, 9.9, 9.0, 9.8, 3.0);
console.log(res);

我们发现在自己实现的avgFn方法中有一个步骤为将arguments克隆出来生成是一个数组。如果对数组的slice方法比较熟悉的话,可以知道当slice方法什么参数都不传的时候就是克隆当前的数组,可以模拟为:

function mySlice () {
    // this->当前要操作的这个数组ary
    var ary = [];
    for (var i = 0; i < this.length; i++) {
        ary[ary.length] = this[i];
    }
    return ary;
};
var ary = [12, 23, 34];
var newAry = mySlice(ary);
console.log(newAry);

所以在avgFn方法中的将arguments转换为数组的操作可以通过call方法来借用Array中的slice方法。

function avgFn() {
    // 1、将类数组转换为数组:把arguments克隆一份一模一样的数组出来      
    // var ary = Array.prototype.slice.call(arguments);
    var ary = [].slice.call(arguments);
    
    // 2、给数组排序,去掉开头和结尾,剩下的求平均数
    ....
}

我们现在的做法是先将arguments转换为数组,然后再操作转换之后的数组,那么可以不可以直接就用arguments而不要先转换为数组呢? 当然是可以的,通过call来借用数组的方法来实现。

function avgFn() {
    Array.prototype.sort.call(arguments , function (a, b) {
        return a - b;
    });
    
    [].shift.call(arguments);
    [].pop.call(arguments);
    
    return (eval([].join.call(arguments, '+')) / arguments.length).toFixed(2);
}
var res = avgFn(9.8, 9.7, 10, 9.9, 9.0, 9.8, 3.0);
console.log(res);
4.3、将类数组转换数组

在4.2中提到了借用数组的slice方法将类数组对象转换为数组,那么通过getElementsByTagName等方法获取的类数组对象是不是也可以借用slice方法来转换为数组对象呢?

var oLis = document.getElementsByTagName('div');
var ary = Array.prototype.slice.call(oLis);
console.log(ary);

在标准浏览器下,的确可以这么用,但是在IE6~8下就悲剧了,会报错:

SCRIPT5014: Array.prototype.slice: 'this' 不是 JavaScript 对象 (报错)

那么在IE6~8下就只能通过循环一个个加到数组中了:

for (var i = 0; i < oLis.length; i++) {
    ary[ary.length] = oLis[i];
}

注意:对于arguments借用数组的方法是不存在任何兼容性问题的。

基于IE6~8和标准浏览器中的区别,抽取出类数组对象转换为数组的工具类:

function listToArray(likeAry) {
    var ary = [];
    try {
        ary = Array.prototype.slice.call(likeAry);
    } catch (e) {
        for (var i = 0; i < likeAry.length; i++) {
            ary[ary.length] = likeAry[i];
        }
    }
    return ary;
}

这个工具方法中用到了浏览器的异常信息捕获,那么在这里也介绍一下吧。

console.log(num);

当我们输出一个没有定义的变量的时候会报错:Uncaught ReferenceError: num is not defined,在JavaScript中,本行报错,下面的代码都不再执行了。

但是如果使用了try..catch捕获异常信息的话,则不会影响下面的代码进行执行,如果try中的代码执行出错了,会默认的去执行catch中的代码。

try {
    console.log(num);
} catch (e) { // 形参必须要写,我们一般起名为e
    console.log(e.message); // --> num is not defined  可以收集当前代码报错的原因
}
console.log('ok');

所以try...catch的使用格式为(和Java中很像):

try {
    // <js code>
} catch (e) {
    // 如果代码报错执行catch中的代码
} finally {
    // 一般不用:不管try中的代码是否报错,都要执行finally中的代码
}

如果有时候既想捕获到信息,又不想让下面的diamante执行,那么应该怎么做呢?

try {
    console.log(num);
} catch (e) {
    // console.log(e.message); // --> 可以得到错误信息,把其进行统计
    // 手动抛出一条错误信息,终止代码执行
    throw new Error('当前网络繁忙,请稍后再试');
    // new ReferenceError --> 引用错误
    // new TypeError --> 类型错误
    // new RangeError --> 范围错误
}
console.log('ok');

个人公众号(icemanFE):分享更多的前端技术和生活感悟



作者:iceman_dev
链接:https://www.jianshu.com/p/00dc4ad9b83f
來源:简书
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
lerobot VLA--SmolVLA代码的讲解 2.图像resize至正方形224x224,图像长宽比不变,其他区域用黑色补充,标记为mask=1,若占位图像(摄像头缺失),则 创建全-1像素的占位图像 标记为mask=0,image为[1, 3, 512, 512],img_mask为True,masks列表长度为2,img_masks为2,因为我这里两个相机。文本嵌入:通过embed_language_tokens() 被转换为嵌入表示,lang_emb 是语言的嵌入,包含了语言的语法和语义信息。1.像素值[0,1]->[-1,1] 阅读详情

相关推荐

VBA学习笔记6:将多个工作表中满足条件的数据汇总到同一个工作表

VBA学习笔记6:将多个工作表中满足条件的数据汇总到同一个工作表

weixin_45355881的博客 4708

javascript call函数探索

我们知道,Array.prototype.slice.call(arguments)能将具有length属性的对象转成数组,除了IE下的节点集合(因为ie下的dom对象是以com对象的形式实现的,js对象与com对象不能进行转换)如: var a={length:2,0:'first',1:'second'}; Array.prototype.slice.call(a);// ["first...

布道 2097

HFSS微带线仿真从零到一:材料参数与求解设置优化指南

在射频电路设计中,微带线仿真涉及电磁场求解与传输线理论,其精度高度依赖材料参数和求解设置。相对介电常数、损耗角正切和导体电导率等参数直接影响特性阻抗与插入损耗,而求解频率、网格划分和参数扫描则决定仿真效率与收敛性。合理设置这些参数可显著提升S参数准确性,避免设计迭代。应用场景包括天线馈线、滤波器和微波互连。本文基于HFSS微带线仿真实践,系统讲解材料选择与参数优化全链路,帮助工程师快速复现可靠模型。

weixin_29192211的博客 82

js函数的方法call()、apply()和bind()详细介绍和区别

在JavaScript中,call()、apply()和bind()是Function对象自带的三个方法,这三个方法的主要作用是改变函数中的this指向。 相同点: 1. apply 、 call 、bind 三者都是用来改变函数的this对象的指向; 2. apply 、 call 、bind 三者都可以利用后续参数传参; 不同点: 1.接受参数上call、bind接收多个参数,apply接收一...

Teheran的博客 1136

手把手教你用OpenCV+Python实现HALCON级模板匹配(附工业案例代码)

本文详细介绍了如何利用开源计算机视觉库OpenCV和Python,构建媲美HALCON商业软件的工业级模板匹配解决方案。通过分析工业检测的核心挑战,文章提供了从模板预处理、多策略融合匹配到应对尺度与旋转的完整代码实现,并附有连接器引脚检测的实战案例,为工业自动化场景下的高精度视觉检测提供了低成本、高可控性的技术路径。

e3f4g5的博客 286

光互联技术演进:OIO、OBO、NPO、CPO四种方案对比与选型指南

光互联技术是解决高速数据中心和AI算力集群带宽瓶颈的关键路径。其核心原理是将光电转换点从面板向交换芯片逐步拉近,以缩短电通道、降低功耗并改善信号完整性。按照光电转换位置与芯片的距离,光互联可分为OIO、OBO、NPO和CPO四种技术路线,各自在功耗、可维护性和成熟度上存在显著差异。在AI训练集群、运营商网络等场景中,选型需综合考量功耗预算、运维体系和供应链生态。本文深入拆解这四种方案的技术细节、工程挑战与部署策略,为光互联技术选型提供实操参考。

weixin_33393017的博客 168

理解Array.prototype.slice.call()方法详解

JavaScript中的Array.prototype.slice.call(arguments)能将有length属性的对象转换为数组(特别注意: 这个对象一定要有length属性). 但有一个例外,IE下的节点集合它不能转换(因为IE下的dom对象是以com对象的形式实现,js对象和com对象不能进行转换) 首先,我们来看看JavaScript中的slice用法, 在JavaScript中A...

alihlz_39337506的博客 6696

jQuery 版本怎么选?别一上来就用最新版,老项目里这个坑很常见

jQuery 是一个封装好的 JavaScript 函数库,简称 JQ它的核心理念是jQuery 有 1.x、2.x、3.x 三个主要版本系列2.0 以上版本不再支持 IE6、IE7、IE8版本选择不能只看“新不新”,而要看项目兼容性和实际需求.min.js是压缩版文件,生产环境常用使用 jQuery 前必须先通过<script>正确引入基本就是没引入或引入失败可以快速绑定点击事件.animate()可以快速实现动画效果,但定位属性要设置好。

Web安全工具库 402

Array.prototype.slice.call方法详解

在很多时候经常看到Array.prototype.slice.call()方法,比如Array.prototype.slice.call(arguments),下面讲一下其原理: 1、基本讲解 1.在JS里Array是一个类 slice是此类里的一个方法 ,那么使用此方法应该Array.prototype.slice这么去用 slice从字面上的意思很容易理解就是截取(当然你不是英肓的话) 这方法如何使用呢? arrayObj.slice(start, [end]) 很显然是截取数组的一部分。 2.我们再看

真爱一生的博客 1239

44、单级静态电流消耗最小化方法及功率优化比较器设计

本文探讨了单级静态电流消耗最小化方法及功率优化的多米诺逻辑比较器设计。通过分析类“AB”输入CMOS差分对电路,提出利用补偿电流源实现高低电流模式切换,提升运算放大器性能;结合VTCMOS与时钟门控技术,在90nm CMOS中设计低功耗比较器,并采用多米诺逻辑提高速度与能效。通过对比传统与改进型多米诺逻辑的静态功耗、动态功耗、延迟和PDP,验证了所提方案在高性能与低功耗方面的优势,适用于便携式设备等对能效要求严苛的应用场景。

pp12345的博客 122

AI视频生成模型训练:从数据准备到部署全流程

咱们这次的目的就像是要建造一座超级厉害的AI视频生成魔法城堡。范围呢,就是从收集建造城堡的材料(数据准备)开始,到把城堡搭建起来(模型训练),再到让城堡能供大家使用(模型部署),涵盖了整个过程的方方面面。接下来我们会先给大家介绍一些重要的术语,就像认识冒险途中的关键道具一样。然后引入一个有趣的故事,带大家进入AI视频生成的奇妙世界,解释核心概念以及它们之间的关系。接着会详细讲解核心算法原理、数学模型和公式,还会有项目实战,带大家亲自体验代码的魅力。

小白菜的博客 400

JavaScript进阶 —— 深入理解 call,apply 和 bind

在JavaScript 中,call、apply 和 bind 是 Function 对象自带的三个方法,这三个方法的主要作用是改变函数中的 this 指向,从而可以达到`接花移木`的效果。本文将对这三个方法进行详细的讲解,并列出几个经典应用场景。1、call。

金戈鐡馬 3868

【LangChain编程:从入门到实践】实现多模态代理

【LangChain编程:从入门到实践】实现多模态代理 关键词:LangChain, 多模态代理, 自然语言处理, 机器学习, 知识图谱, 对话系统, 代码生成, AI代理 1. 背景介绍 随着人工智

欢迎来到我的优快云空间!这里聚焦AI大模型应用实战,分享前沿技术、实战案例与开发经验。 581

深入理解JS中call,apply及bind的用法

apply 语法:func.apply(thisArg, [argsArray]) 参数 thisArg:调用func的this值,如果处于非严格模式下,则指定为 null 或 undefined 时会自动替换为指向全局对象 argsArray:调用func的传参(参数需要放到一个数组中) 核心概念(借用) 举个栗子 有一天你一时兴起想做个红烧肉,但万事具备只欠口锅,但是买一个又不...

a15180180753的博客 294

Probability and Statistics - 4th edition

Probability and Statistics - 4th edition

VC中sqlite的使用

在VC中对sqlite的使用,实现数据库大批数据的快速插入,读取数据库中的数据在ListCtrl中显示

深入理解js中的apply、call、bind

概述 js中的apply,call都是为了改变某个函数运行时的上下文环境而存在的,即改变函数内部的this指向。 apply() apply 方法传入两个参数:一个是作为函数上下文的对象,另外一个是作为函数参数所组成的数组。 var student = { name : 'xiaoming' } function getName(firstName , lastName){

feijiges的博客 278

数学建模模型总结

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

深入理解Javascript中call、apply、bind

今天在github上看到一个博文深受启发,所以想融合自己的想法将call、apply、bind的知识分享给大家。 可能大家都知道这三个api是改变this指向的,但是这三个api如何做到改变this指向的,这里我要跟大家一起学习,一起探讨的。 接下来给大家看一段代码 var foo = { value:1, space:function(){ console.log(this.value) } }; foo.space()// 1 大家可以看到上面的结果显示为1,这个时候可能会有人好奇,举这个例

m0_49680854的博客 192

Data-Structures-and-Algorithm-Analysis-in-Java.pdf

作者: Weiss, Mark A. 出版社: Addison Wesley Data Structures and Algorithm Analysis in Java is an “advanced algorithms” book that fits between traditional CS2 and Algorithms Analysis courses. In the old ACM Curriculum Guidelines, this course was known as CS7. This text is for readers who want to learn good programming and algorithm analysis skills simultaneously so that they can develop such programs with the maximum amo...

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

本文将介绍JavaScript中的call、apply、bind方法,以及它们如何实现函数的执行上下文绑定。通过了解这些方法,开发者可以更好地利用JavaScript的特性,提高代码的灵活性和可复用性。

你若盛开,清风自来 946

深入理解 JavaScript 中的 bind、apply、call:用法与实现

JavaScript 中 bind、apply 和 call 方法都用于改变函数执行时的 this 指向,但各有特点:call 和 apply 会立即执行函数,区别在于参数传递方式;bind 则返回一个新函数,允许延迟执行。这些方法在对象方法借用、参数处理、异步回调等场景中非常实用。本文详细解析了三者的用法差异,并通过手写实现揭示了其底层原理,包括如何处理 this 绑定、参数合并以及构造函数调用等特殊情况。掌握这些方法有助于开发者更灵活地控制函数执行上下文,是深入理解 JavaScript 函数机制的关键

pzhdv的博客 1835

JS中的apply,call,bind深入理解

在Javascript中,Function是一种对象。Function对象中的this指向决定于函数被调用的方式。使用apply,call 与 bind 均可以改变函数对象中this的指向,在说区别之前还是先总结一下三者的相似之处:1、都是用来改变函数的this对象的指向的。2、第一个参数都是this要指向的对象。3、都可以利用后续参数传参。 call方法:语法:call([thisOb...

weixin_30756499的博客 97

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

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

javaThinker的专栏 831

JavaScript之call、apply、bind深入理解

一、函数的三种角色 首先要先了解在函数本身会有一些自己的属性,比如: length:形参的个数; name:函数名; prototype:类的原型,在原型上定义的方法都是当前这个类的实例的公有方法; __proto__:把函数当做一个普通对象,指向Function这个类的原型 函数在整个JavaScript中是最复杂也是最重要的知识,对于一个函数来说,会存在多种角色: functio...

shittihs的博客 409

js call、apply 和 bind 方法的深入理解

目录 一、概述 二、详解 call()、apply() 和 bind()方法 1、apply()方法 2、call()方法 3、bind()方法 三、call()、apply() 和 bind()方法的核心理念 四、手写call()、apply() 和 bind()方法(中高级前端面试题)★★★★★ 1、手写call()方法 2、手写apply()方法 3、手写bind()方法 五、call()、apply() 和 bind()方法的实际应用 1、如...

青蛙king的博客 475

深入理解JavaScript中的call、apply、bind方法的区别

转载自:http://www.jb51.net/article/85367.htm 在JavaScript 中,this的指向是动态变化的,很可能在写程序的过程中,无意中破坏掉this的指向,所以我们需要一种可以把this的含义固定的技术,于是就有了call,apply 和bind这三个方法,来改变函数体内部 this 的指向,因为函数存在「定义时上下文」和「运行时上下文」以及「

mozuncangtianbaxue的博客 394

JavaScript中call,apply,bind的深入理解与对比

在JavaScript中,call、apply和bind是Function对象自带的三个方法,这三个方法的主要作用是改变函数中的this指向。 call、apply、bind方法的共同点和区别: apply、call、bind三者都是用来改变函数的this对象的指向的; apply、call、bind三者第一个参数都是this要指向的对象,也就是想指定的上下文(函数的每次调用都会...

fly_home_ysc的博客 265

【JavaScript】深入理解call,以及与apply、bind的区别

一、call call有两个妙用 1、继承(我前面的文章有提到用call实现call继承,有兴趣可以看下。https://www.cnblogs.com/pengshengguang/p/10547624.html) 2、修改函数运行时this的指向(今天要说的) // 代码段一 var obj = {name: 'psg'}; function fn...

ass201295的专栏 296
上一篇: GET请求中URL的最大长度限制总结
下一篇: e.target与e.currentTarget的作用
ole_triangle_java
博客等级 码龄10年 82粉丝 83原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值