首先这三个函数的目的都是实现函数调用
- apply
foo.apply(foo,[2,3]) //用apply调用foo
function foo(a,b) {
console.log(this)
console.log(a)
console.log(b)
}
foo.apply(foo,[2,3]) //用apply调用函数foo
返回的结果是:
也就是说apply函数的第一个参数是内部this的指向,后面的数组会解构成函数真正的参数。apply方法是ES5中常见的方法,可以用来劫持另一个对象的方法和属性,如下面的例子:
function Person(name, age) {
this.name = name;
this.age = age;
}
function Student(name, age, grade) {
Person.apply(this, arguments);
this.grade = grade;
}
var person = new Student('zyp', 18, '一年级')
console.log('person',person)
输出结果为:
也就是说Student方法通过apply方法实现了对Person方法的继承,使得通过Student构造出来的实例包含Person实例的name和age属性。
这里要注意的是,apply方法的第一个参数是apply前面一个方法的this上下文,第二个参数可以是一个数组或者是类数组对象(上例中的arguments就是类数组对象),apply方法在执行过程中会将其展开成参数列表(arg1,arg2,
arg3…)。这可能是一种实现类似下列ES6中class中继承概念的一种野蛮方法。
class Person1 {
constructor(name, age) {
this.name = name;
this.age = age;
}
}
class Student1 extends Person1 {
constructor(name, age, grade) {
super(name, age)
this.grade = grade
}
}
var person1 = new Student1('zyp1', 18, '一年级')
console.log('person1',person1)
输出的结果为:
- call
foo.call(foo,1,2) //用call调用foo
call方法和apply方法的功能基本一致,区别在使用上,call方法除第一个参数以外,其他参数构成参数列表。
function foo(a,b) {
console.log(this)
console.log(a)
console.log(b)
}
foo.call(this,1,2) //用call调用函数foo
返回的结果是:
function Person(name, age) {
this.name = name;
this.age = age;
}
function Student(name, age, grade) {
Person.call(this, name, age);
this.grade = grade;
}
var person = new Student('zyp', 18, '一年级')
console.log('person',person)
输出结果跟使用apply方法一致。
- bind
foo.bind(foo,3,4).call() // 用bind调用foo
返回的结果是:
也就是说bind函数的作用是将参数传递给原函数的拷贝,然后执行call就可以调用这个拷贝函数了