深入理解 call,apply 和 bind

深入理解 call,apply 和 bind

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

1、call(thisArgs [,args...])

该方法可以传递一个thisArgs参数和一个参数列表,thisArgs 指定了函数在运行期的调用者,也就是函数中的 this 对象,而参数列表会被传入调用函数中。thisArgs 的取值有以下四种情况:

  • 不传,或者传null,undefined, 函数中的 this 指向 window 对象
  • 传递另一个函数的函数名,函数中的 this 指向这个函数的引用
  • 传递字符串、数值或布尔类型等基础类型,函数中的 this 指向其对应的包装对象,如 String、Number、Boolean
  • 传递一个对象,函数中的 this 指向这个对象

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

function a(){

    console.log(this);//输出函数a中的this对象

}

function b(){}//定义函数b

 

var obj = {name:'onepixel'};//定义对象obj

 

a.call();//window

a.call(null);//window

a.call(undefined);//window

a.call(1);//Number

a.call('');//String

a.call(true);//Boolean

a.call(b);// function b(){}

a.call(obj);//Object

这是call 的核心功能,它允许你在一个对象上调用该对象没有定义的方法,并且这个方法可以访问该对象中的属性,至于这样做有什么好处,我待会再讲,我们先看一个简单的例子:

 

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

var a = {

 

    name:'onepixel',//定义a的属性

 

    say:function(){//定义a的方法

        console.log("Hi,I'm function a!");

    }

};

 

function b(name){

    console.log("Post params: "+ name);

    console.log("I'm "+this.name);

    this.say();

}

 

b.call(a,'test');

>>

Postparams: test

I'm onepixel

I'm function a!

当执行b.call 时,字符串`test`作为参数传递给了函数b,由于call的作用,函数b中的this指向了对象a, 因此相当于调用了对象a上的函数b,而实际上a中没有定义b 。

2、apply(thisArgs [,args[]])

apply 和 call 的唯一区别是第二个参数的传递方式不同,apply 的第二个参数必须是一个数组(或者类数组),而 call 允许传递一个参数列表。值得你注意的是,虽然 apply 接收的是一个参数数组,但在传递给调用函数时,却是以参数列表的形式传递,我们看个简单的例子:

1

2

3

4

5

function b(x,y,z){

    console.log(x,y,z);

}

 

b.apply(null,[1,2,3]);// 1 2 3

apply 的这个特性很重要,我们会在下面的应用场景中提到这个特性。

3、bind(thisArgs [,args...])

bind是ES5 新增的一个方法,它的传参和call类似,但又和 call/apply 有着显著的不同,即调用 call 或 apply 都会自动执行对应的函数,而 bind 不会执行对应的函数,只是返回了对函数的引用。粗略一看,bind 似乎比call/apply 要落后一些,那ES5为什么还要引入bind 呢?

其实,ES5引入 bind 的真正目的是为了弥补 call/apply 的不足,由于 call/apply 会对目标函数自动执行,从而导致它无法在事件绑定函数中使用,因为事件绑定函数不需要我们手动执行,它是在事件被触发时由JS 内部自动执行的。而 bind 在实现改变函数 this 的同时又不会自动执行目标函数,因此可以完美的解决上述问题,看一个例子就能明白:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

var obj = {name:'onepixel'};

 

/**

 * 给document添加click事件监听,并绑定onClick函数

 * 通过bind方法设置onClick的this为obj,并传递参数p1,p2

 */

document.addEventListener('click',onClick.bind(obj,'p1','p2'),false);

 

//当点击网页时触发并执行

function onClick(a,b){

    console.log(

            this.name,//onepixel

            a,//p1

            //p2

    )

}

当点击网页时,onClick 被触发执行,输出onepixel p1 p2, 说明 onClick 中的 this 被 bind 改变成了obj 对象

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值