您当前的位置: 首页 >  Java

顺其自然~

暂无认证

  • 2浏览

    0关注

    1317博文

    0收益

  • 0浏览

    0点赞

    0打赏

    0留言

私信
关注
热门博文

javascript中call()、apply()、bind()的用法终于理解

顺其自然~ 发布时间:2020-06-01 14:50:49 ,浏览量:2

其实是一个很简单的东西,认真看十分钟就从一脸懵B 到完全 理解!

在 javascript 中,call 和 apply 都是为了改变某个函数运行时的上下文(context)而存在的,换句话说,就是为了改变函数体内部 this 的指向。 JavaScript 的一大特点是,函数存在「定义时上下文」和「运行时上下文」以及「上下文是可以改变的」这样的概念。

function fruits() {}
fruits.prototype = {
    color: "red",
    say: function() {
        console.log("My color is " + this.color);
    }
}
var apple = new fruits;
apple.say();    //My color is red

但是如果我们有一个对象banana= {color : "yellow"} ,我们不想对它重新定义 say 方法,那么我们可以通过 call 或 apply 用 apple 的 say 方法:

banana = {
    color: "yellow"
}
apple.say.call(banana);     //My color is yellow
apple.say.apply(banana);    //My color is yellow

所以,可以看出 call 和 apply 是为了动态改变 this 而出现的,当一个 object 没有某个方法(本例子中banana没有say方法),但是其他的有(本例子中apple有say方法),我们可以借助call或apply用其它对象的方法来操作。

对于 apply、call 二者而言,作用完全一样,只是接受参数的方式不太一样。例如,有一个函数定义如下:

var func = function(arg1, arg2) {
     
};

就可以通过如下方式来调用:

func.call(this, arg1, arg2);
func.apply(this, [arg1, arg2])

其中 this 是你想指定的上下文,他可以是任何一个 JavaScript 对象(JavaScript 中一切皆对象),call 需要把参数按顺序传递进去,而 apply 则是把参数放在数组里。  

bind

在讨论bind()方法之前我们先来看一道题目:

var altwrite = document.write;
altwrite("hello");

结果:Uncaught TypeError: Illegal invocation

相当于下面的语句:

//var altwrite = document.write;
var altwrite = write;
altwrite("hello");

altwrite()函数使this指向global或window对象,导致执行时提示非法调用异常,正确的方案就是使用bind()方法:

altwrite.bind(document)("hello")

当然也可以使用call()方法:

altwrite.call(document, "hello")

bind()最简单的用法是创建一个函数,使这个函数不论怎么调用都有同样的this值。常见的错误就像上面的例子一样,将方法从对象中拿出来,然后调用,并且希望this指向原来的对象。如果不做特殊处理,一般会丢失原来的对象。使用bind()方法能够很漂亮的解决这个问题:

this.num = 9; 
var mymodule = {
  num: 81,
  getNum: function() { 
    console.log(this.num);
  }
};

mymodule.getNum(); // 81

var getNum = mymodule.getNum;
getNum(); // 9, 因为在这个例子中,"this"指向全局对象

var boundGetNum = getNum.bind(mymodule);
boundGetNum(); // 81

先看明白下面:

例1

这里写图片描述

  obj.objAge;  //17
  obj.myFun()  //小张年龄undefined

例2这里写图片描述

 shows()  //盲僧 

比较一下这两者this 的差别,第一个打印里面的this 指向obj,第二个全局声明的shows()函数 this 是window ;

1,call()apply()bind() 都是用来重定义 this 这个对象的!

如:这里写图片描述

  obj.myFun.call(db);    //德玛年龄99
   obj.myFun.apply(db);    //德玛年龄99
   obj.myFun.bind(db)();   //德玛年龄99

以上除了bind 方法后面多了个 () 外 ,结果返回都一致!

由此得出结论,bind 返回的是一个新的函数,你必须调用它才会被执行

2,对比call 、bind 、 apply 传参情况下这里写图片描述

  obj.myFun.call(db,'成都','上海');     //德玛 年龄 99  来自 成都去往上海
  obj.myFun.apply(db,['成都','上海']);        //德玛 年龄 99  来自 成都去往上海  
  obj.myFun.bind(db,'成都','上海')();         //德玛 年龄 99  来自 成都去往上海
   obj.myFun.bind(db,['成都','上海'])();   //德玛 年龄 99  来自 成都,上海去往undefined

微妙的差距!

从上面四个结果不难看出

  • call 、bind 、 apply 这三个函数的第一个参数都是 this 的指向对象,第二个参数差别就来了:
  • call的参数是直接放进去的,第二第三第n个参数全都用逗号分隔,直接放到后面 obj.myFun.call(db,'成都', ... ,'string' );
  • apply的所有参数都必须放在一个数组里面传进去 obj.myFun.apply(db,['成都', ..., 'string' ]);
  • bind除了返回是函数以外,它 的参数和call 一样。

当然,三者的参数不限定是string类型,允许是各种类型,包括函数 、 object 等等!

关注
打赏
1662339380
查看更多评论
立即登录/注册

微信扫码登录

0.0419s