JavaScript——函数调用 call()、apply()、bind()

立即调用(call now)

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

区别:作用一样,接受参数的方式不一样

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

 

例如有一个函数定义如下

let fun = function(arg1,arg2){}

 

call()

传参

fun.call(this,arg1,arg2)

 

apply()

传参

fun.apply(this,[arg1,arg2])

 


 

实例demo

  • 获取数组中的最大值和最小值

    

var  numbers = [5, 458 , 120 , -215 ]; 
var maxInNumbers = Math.max.apply(Math, numbers),   //458
    maxInNumbers = Math.max.call(Math,5, 458 , 120 , -215); //458

  PS:number 本身没有 max 方法,但是 Math 有,我们就可以借助 call 或者 apply 使用其方法。  

 


 

新建函数(new function)

bind()

  • bind() 方法创建一个新的函数,在 bind() 被调用时,这个新函数的 this 被指定为 bind() 的第一个参数,而其余参数将作为新函数的参数,供调用时使用。
  • 在Javascript中,多次 bind() 是无效的。
let a = function(){}
let b = a
console.log(a==b); // true
            
let c = a.bind() // 新复制的函数,所以会和原来的不一样
console.log(a==c); // false

 

通常我们会使用 _this , that , self 等保存 this ,这样我们可以在改变了上下文之后继续引用到它。

例如这样:

var foo = {
    num: 1,
    change: function(){
        let_this = this;
        $('.btn').on('click',function(event) {
            console.log(_this.num);     //1
        });
    }
}

 

如果不使用常量保存this的话,this将会指向window而不是foo函数。

可以使用bind()更加优雅的解决这个问题

var foo = {
    num: 1,
    change: function(){
        $('.btn').on('click',function(event) {
            console.log(this.num);      //1
        }.bind(this));
    }
}

在上述代码里,bind() 创建了一个函数,当这个click事件绑定在被调用的时候,它的 this 关键词会被设置成被传入的值(这里指调用bind()时传入的参数)。因此,这里我们传入想要的上下文 this(其实就是 foo ),到 bind() 函数中。然后,当回调函数被执行的时候, this 便指向 foo 对象。

  

demo

       let bar = function(){
            console.log(this.x);
            }
            letfoo = {
            x:3
            }
            bar(); // undefined
            bar.bind(foo)(); // 3

这里我们创建了一个新的函数 func,当使用 bind() 创建一个绑定函数之后,它被执行的时候,它的 this 会被设置成 foo , 而不是像我们调用 bar() 时的全局作用域。

 

call、apply、bind比较

demo1:

var obj = {
    x: 81,
};
 
var foo = {
    getX: function() {
        return this.x;
    }
}
 
console.log(foo.getX.bind(obj)());  //81
console.log(foo.getX.call(obj));    //81
console.log(foo.getX.apply(obj));   //81

 

三个输出的都是81,但是注意看使用 bind() 方法的,他后面多了对括号。

也就是说,区别是,当你希望改变上下文环境之后并非立即执行,而是回调执行的时候,使用 bind() 方法。而 apply/call 则会立即执行函数。

 

总结:

  • apply 、 call 、bind 三者都是用来改变函数的this对象的指向的;
  • apply 、 call 、bind 三者第一个参数都是this要指向的对象,也就是想指定的上下文;
  • apply 、 call 、bind 三者都可以利用后续参数传参;
  • bind 是返回对应函数,便于稍后调用;apply 、call 则是立即调用 。

 

posted @ 2020-10-23 16:49  小昱同学  阅读(202)  评论(0编辑  收藏  举报