欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

call、apply和bind方法的用法以及区别

程序员文章站 2022-07-14 14:27:16
...

前言

最近在学习的时候,遇见了apply()函数,发现自己对于call,bind函数不了解,所以今天来看看。

正文

因为这三个函数的作用都是改变函数运行时this的指向,所以我们要来先看看this。

函数调用有以下几种方法:

方法调用模式:
当一个函数被保存为对象的一个方法时,如果调用表达式包含一个提取属性的动作,那么它就是被当做一个方法来调用,此时的this被绑定到这个对象。

    var a =  1
    var obj = {
      a: 2,
      fn(){
        return this.a;
      }
    }
    console.log(obj.fn()); //2

DOM对象绑定事件也属于方法调用模式,因此它绑定的this就是事件源DOM对象。

    document.addEventListener('click',function(){
      console.log(this); //document
      setTimeout(function(){
        console.log(this); //window
      },100)
    },false)

函数调用模式:
就是普通函数的调用,此时的this被绑定到window

普通的函数调用:

    function fn1(){
          console.log(this)//window
        }
    fn1()

把函数赋值之后在调用:

var a = 1
var obj1 = {
    a:2,
    fn:function(){
        console.log(this.a)
    }
}
var fn1 = obj1.fn
fn1()//1

这里obj1.fn是一个函数function(){console.log(this.a)},此时fn1就是不带任何修饰的函数调用,function(){console.log(this.a)}.call(undefined),按理说打印出来的 this 应该就是 undefined 了吧,但是浏览器里有一条规则:如果你传的 context 就 null 或者 undefined,那么 window 对象就是默认的 context(严格模式下默认 context 是 undefined) 因此上面的this绑定的就是window,它也被称为隐性绑定。

回调函数
先来看第一个函数:

var a = 1
function f1(fn){
    fn()
    console.log(a)//1
}
f1(f2)

function f2(){
    var a = 2
}

在改写一下这个函数:

var a = 1
function f1() {
  (function f2(){
    var a =2
  })()
  console.log(a);
}

仍然是f1.call(undefined)所以this还是window

构造器调用模式:
new一个函数时,背地里会将创建一个连接到prototype成员的新对象,同时this会被绑定到那个新对象上

function Persion(name) {
//这里this指向实例
  this.name = name,
  this.sayName = function sayName(){
    console.log(this.name);
  }
}

var a= new Persion('ccc')
a.sayName() //ccc

call函数:
call 方法第一个参数是要绑定给this的值,后面传入的是一个参数列表。当第一个参数为null、undefined的时候,默认指向window。

var arr = [1, 2, 3, 89, 46]
var max = Math.max.call(null, arr[0], arr[1], arr[2], arr[3], arr[4])//89

举一个例子:

var obj = {
    message: 'My name is: '
}

function getName(firstName, lastName) {
    console.log(this.message + firstName + ' ' + lastName)
}

getName.call(obj, 'Dot', 'Dolby')  //My name is: Dot Dolby

apply函数:

apply接受两个参数,第一个参数是要绑定给this的值,第二个参数是一个参数数组。当第一个参数为null、undefined的时候,默认指向window。

var obj = {
    message: 'My name is: '
}

function getName(firstName, lastName) {
    console.log(this.message + firstName + ' ' + lastName)
}

getName.apply(obj, ['Dot', 'Dolby']) //My name is: Dot Dolby

事实上apply 和 call 的用法几乎相同, 唯一的差别在于:当函数需要传递多个变量时, apply 可以接受一个数组作为参数输入, call 则是接受一系列的单独变量。

bind函数
和call很相似,第一个参数是this的指向,从第二个参数开始是接收的参数列表。区别在于bind方法返回值是函数以及bind接收的参数列表的使用。

  • bind返回值是函数
var obj = {
    name: 'Dot'
}

function printName() {
    console.log(this.name)
}

var dot = printName.bind(obj)
console.log(dot) // function () { … }
dot()  // Dot

bind 方法不会立即执行,而是返回一个改变了上下文 this 后的函数。而原函数 printName 中的 this 并没有被改变,依旧指向全局对象 window。

  • 参数的使用
function fn(a, b, c) {
    console.log(a, b, c);
}
var fn1 = fn.bind(null, 'Dot');

fn('A', 'B', 'C');            // A B C
fn1('A', 'B', 'C');           // Dot A B
fn1('B', 'C');                // Dot B C
fn.call(null, 'Dot');      // Dot undefined undefined

call 是把第二个及以后的参数作为 fn 方法的实参传进去,而 fn1 方法的实参实则是在 bind 中参数的基础上再往后排。

总结

call、apply和bind函数存在的区别:
bind返回对应函数, 便于稍后调用; apply, call则是立即调用。

引用自:

https://www.jianshu.com/p/bc541afad6ee