apply和call和bind三个方法的区别

相同点

这三个函数都是function的原型方法

这三个函数都可以改变函数的作用域

不同点

对于call和apply来说,他们是在调用后函数立即执行,但是call的函数参数(从第二个参数开始就是函数参数)可以有多个,而apply的函数参数只能是一个数组。

而对于bind来说,他执行完后会返回一个新的在这个作用域下的函数

参数

.call(函数作用域,剩余参数1,剩余参数2...) 剩余参数会作为该函数的参数

.apply(函数作用域,数组) 会把数组的元素作为该函数的参数。类似于.call(...数组)

.bind(函数作用域,剩余参数1,剩余参数2....) 剩余参数会作为该函数的默认参数。

如果参数为null或undefined,则视为绑定在全局作用域下

返回值

call和apply会立即执行函数,返回一个该函数的返回值

bind会返回一个带有默认参数(如果指定的话)的新函数。

用法

call

1 实现继承

function People(name, age) {
  this.name = name;
  this.age = age;
  this.profession = "citizen";
  this.sayHi = function () {
    console.log("Hi");
  }
}
function Student(name, age) {
  People.call(this, name, age);
  this.profession = "student";
  this.study = function () {
    console.log("i am studying");
  }
}//Student继承自People 如果我们直接使用People(name,age) 则会导致People函数的作用域为global

2 为匿名函数指定作用域

bind

1.创建偏函数

带有预设参数的函数

function add(n1, n2) { return n1 + n2 }
var add_s = add.bind(null, 25);//此时add_s的第一个参数永远是25

2.配合setTimeout

当用setTimeout方法的时候,回调函数的作用域为timeout作用域,可看如下实例

var obj = {
  age: 18,
  sayAge: function () {
    console.log(this);
 /* 输出
   	Timeout {
  		_idleTimeout: 1000,
  		_idlePrev: null,
  		_idleNext: null,
  		_idleStart: 31,
  		_onTimeout: [Function: sayAge],
  		_timerArgs: undefined,
  		_repeat: null,
  		_destroyed: false,
  		[Symbol(refed)]: true,
  		[Symbol(asyncId)]: 2,
  		[Symbol(triggerId)]: 1
	}*/
    console.log(this.age);//undefined
  }
}
setTimeout(obj.sayAge, 1000);

我们看到,通过setTimeout调用的回调函数,他的作用域是Timeout,而通常情况下,我们并不需要这个作用域,所以可以通过bind方法,改变回调函数的作用域(啥?你说为啥不用call,因为setTimeout方法的参数是一个回调函数)。其实,不光是setTimeout,还有很多涉及回调的方法,例如promise都需要作用域绑定,这里就不赘述了。

function LateBloomer() {
  this.petalCount = Math.ceil(Math.random() * 12) + 1;
}

// 在 1 秒钟后声明 bloom
LateBloomer.prototype.bloom = function() {
  window.setTimeout(this.declare.bind(this), 1000);//通过bind函数绑定了declare这个原型函数的作用域
};

LateBloomer.prototype.declare = function() {
  console.log('I am a beautiful flower with ' +
    this.petalCount + ' petals!');//this指向的是LateBloomer这个函数
};

var flower = new LateBloomer();
flower.bloom();  // 一秒钟后, 调用 'declare' 方法

参考文献

apply call [bind](

posted @ 2020-07-13 15:03  菁华如梦  阅读(186)  评论(0)    收藏  举报