JavaScript中apply、call、bind方法详解及this指向规则

作者:小括号

时间:2026-10-21

浏览:509

本文详细解析JavaScript中apply、call和bind三个核心方法的用法与区别。通过对比参数传递方式,阐述它们如何改变函数执行时的this指向。结合Math.max、数组操作及事件处理等实际案例,说明如何灵活运用这些方法优化代码。同时深入剖析this在不同执行环境下的绑定规则,帮助开发者准确掌握上下文对象的使用。

文章目录

apply与call方法详解

fun.apply(context,[argsArray])

该方法用于立即调用fun函数,并将函数内部的this指向传入的context对象,从而实现同一方法在不同对象间的复用。

context:传入的对象,用于替代fun函数原本的this指向。

argsArray:一个数组或类数组对象,其中的元素会被展开作为单独的实参传递给fun函数,需注意参数的顺序。

fun.call(context,[arg1],[arg2],[…])

其功能与apply类似,区别在于参数传递方式不同。call要求参数逐个传入;若参数数量不确定,则应使用apply。

应用场景示例:

Math.max()仅接收单独参数,通过以下方式可在数组上使用max方法: Math.max.apply(null, array); //将array数组参数展开为单独参数传入 Array.prototype.push.apply(arr1,arr2); //将一个数组拆开push到另一个数组中;若不使用apply,后续数组参数将被视为单个元素push进去。 Array.prototype.slice.call(arguments); //在类数组对象上使用slice方法


function isArray(obj){
  return Object.prototype.toString.call(obj) === '[object Array]' ;
}  //验证是否是数组

bind方法及其特性

fun.bind(context,[arg1],[arg2],[…])

使fun方法执行时的context永久固定不变。

arg1:要传递到新函数的参数列表。

bind返回一个新函数供后续调用,其函数体与原函数fun一致,但新函数的this指向新传入的context对象。新函数具备bind指定的初始参数arg1/arg2...,后续调用新函数时的实参需排在已有参数之后。


//原来的函数有4个参数
var displayArgs = function (val1, val2, val3, val4) {
  console.log(val1 + " " + val2 + " " + val3 + " " + val4);
}
var emptyObject = {};
// 生成新函数时bind方法指定了2个参数,则新函数会带着这个两个实参
var displayArgs2 = displayArgs.bind(emptyObject, 12, "a");
// 调用时传入另2个参数,要在bind方法传入的2个实参后面
displayArgs2("b", "c");
// Output: 12 a b c

在事件处理函数中使用bind:


var obj = {
  arg1 : 1,
  attach: function(){
    //var self = this; 普通传入this 的方法
    $('xxx').on('click',function (event) {
      console.log(this.arg1);//若不绑定this,回调函数中的this常指目标元素
     }.bind(this));  //使用bind方法绑定this
  }
}    


使用bind()方法改写slice()方法:


var _Slice = Array.prototype.slice;
var slice = Function.prototype.call.bind(_Slice);
slice(…);

bind()兼容IE5~IE8的处理方案:


if (!Function.prototype.bind) {
  Function.prototype.bind = function(context) {
    var self = this, // 调用bind方法的目标函数
    args = arguments;
    return function() {
      self.apply(context, Array.prototype.slice.call(args, 1));//参数个数不确定时用apply
    }
  }
}   

通常情况下,setTimeout()中的this指向window或global对象。当使用类的方法时需要this指向类实例,即可使用bind()将this绑定到调用对象,无需通过self方式传入this。

this指向规则解析

this

this对象是在函数运行时基于函数的执行环境绑定的:在全局函数中,this等于window;当函数被当作某个对象的方法调用时,this等于那个对象。

判断方法:this与定义位置无关,函数运行时,若存在.运算符,this指.前的对象;若无,this指window。若使用new关键字调用时,指代新对象。存在apply/call/bind时,指代第一个参数。


/*例1*/
function foo() {
  console.log( this.a );
} 
var obj2 = {
  a: 42,
  foo: foo
};
var obj1 = {
  a: 2,
  obj2: obj2
};
obj1.obj2.foo(); // 42;当foo函数被调用时,其本身是归obj2所拥有
/*例2*/
function foo() {
  console.log( this.a );
} 
var obj = {
  a: 2,
  foo: foo
};
var bar = obj.foo;   // bar引用foo函数本身
var a = "global";   // 全局对象的属性
bar();        // "global" ;  

在一个HTML DOM事件处理程序里面,this始终指向这个处理程序被所绑定到的DOM节点。

实用工具推荐

电子包浆

绿化、压缩、噪点和虚拟水印,自由调节做旧程度。

使用 ›
图片压缩

选择画质和输出格式,预览压缩前后的大小。

使用 ›
相关文章