• call,apply和bind


    call和apply

    call和aplly作用完全一样,都是在特定的上下文中调用函数,或者说改变函数内部的this指向;区别仅在于接收参数的方式不同。

    var dog = {
      name: "dog"
    };
    var cat = {
      name: "cat"
    };
    var sayName = function (age, gender) {
      console.log(this.name + "," + age + "," + gender)
    };
    sayName(); //undefined
    sayName.call(dog, 2, "male"); //dog,2,male
    sayName.call(cat, 3, "female"); //cat,3,female
    sayName.apply(dog, [2, "male"]); //dog,2,male
    sayName.apply(cat, [3, "female"]); //cat,3,female
    
    

    我们在全局环境定义了一个sayName方法,调用该方法时会将当前环境的name属性(this.name)显示到控制台上。当我们在全局环境调用sayName()时,由于全局环境并没有this.name属性(注意,浏览器window对象上有name属性,这里指node环境),因此显示了undefined。
    使用call或者apply,就可以改变函数的执行环境,或者说改变函数内部的this指向。例如sayName.call(dog),表示将sayName内部的this指向了dog对象,因此this.name显示为"dog"。当我们调用sayName.call(cat)时,sayName内部的this又指向了cat对象。
    可以看出来,call与apply的作用完全相同,区别仅在于接收参数的方式不同。

    fn.call(context, arg1, arg2, ...)
    fn.apply(context, [arg1, arg2, ...])
    

    call和apply接收的第一个参数都是函数的运行环境。使用call时传递给函数的参数必须逐个传入,而使用apply时函数的参数应该是一个数组,或者类数组对象(如arguments对象)。至于使用call还是apply,完全取决于采用哪种方法给函数传递参数更方便。在不需要给函数传递参数的情况下,使用哪个方法都无所谓。

    bind

    bind也可以改变函数内部的this指向,区别在于bind不会直接调用该函数,而是返回一个绑定了this的函数,由你来决定什么时候调用。

    var dog = {
      name: "dog"
    };
    var cat = {
      name: "cat"
    };
    var sayName = (function (age, gender) {
      console.log(this.name + "," + age + "," + gender)
    }).bind(dog, 3, "male");
    
    sayName.call(cat, 2, "female"); //dog,3,male
    

    我们创建sayName函数时,使用bind将该函数的this指向了dog对象,同时还绑定了传入函数的参数。
    现在我们调用sayName.call(cat, 2, "female"),发现不论是this对象,还是传入函数的参数,都是之前被绑定的值。
    bind像call一样接受多个参数,第一个参数为context(即内部this值),后面的参数依次为函数接收的参数

    用途

    call和apply适合用在只需要临时改变函数运行环境的地方,可以用来共享一些方法。最经典、实用的莫过于Array.prototype.slice.call(arguments)了,利用call可以直接在类数组对象上调用Array的slice方法,方便的将类数组对象转换成真正的数组对象。

    bind方法适合用在将某个函数以值的形式传递,同时该函数必须在特定的环境中执行的时候,例如一些事件处理程序,回调函数和setTimeout()、setInterval()等。例如:

    var alarmClock = {
      time: function () {
        return new Date();
      },
      alarm: function () {
        console.log(this.time())
      }
    };
    setInterval(alarmClock.alarm,1000); //TypeError: this.time is not a function
    setInterval(alarmClock.alarm.bind(alarmClock),1000); //Thu May 18 2017 12:32:44 GMT+0800 (中国标准时间)
    

    当直接将alarmClock.alarm传递给setInterval()时,因为alarmClock.alarm调用的环境是setInterval,即全局环境,其中没有time方法,于是TypeError。
    通过使用bind(alarmClock),就可以将alarmClock.alarm的运行环境绑定到alarmClock对象上,这样每次执行都可以获得正确的结果。

    另外,bind还可以用在函数柯里化。

    总结

    call,apply和bind其实很简单,无非就是改变了函数内部的this指向而已,区别仅仅是使用的方法和场景不同。

  • 相关阅读:
    svn 更新
    首尾渐变
    sublime常用快捷键
    【CSS3】transition过渡和animation动画
    JS实现奇偶数的判断
    style、currentStyle、getComputedStyle区别介绍
    JavaScript中判断对象类型的种种方法
    CSS3 animation动画,循环间的延时执行时间
    EMCA创建em资料库时报错
    OS Kernel Parameter.semopm
  • 原文地址:https://www.cnblogs.com/huanglei-/p/6870236.html
Copyright © 2020-2023  润新知