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' 方法

浙公网安备 33010602011771号