call 和 apply
call()、apply()分别是Function原型定义的2个方法,Function.prototype.call()、Function.prototype.apply()。call()、apply() 方法的作用都是调用一个函数, 它们的区别是传入参数不同。
apply接收两个参数,第一个参数指定函数体内this对象的指向,第二个参数是数组或类数组(如arguments)
var fun = function (a, b, c) {
console.log(a); // 1
console.log(b); // 2
console.log(c); // 3
}
fun.apply(null, [1, 2, 3]);
// fun 参数a、b、c分别对应传入数组[1, 2, 3]参数
call接受若干个参数的列表,第一个参数同样是指定fun函数内的this值,第二个参数开始是指定的参数列表。
var fun = function (a, b, c) {
console.log(a); // 1
console.log(b); // 2
console.log(c); // 3
}
fun.call(null, 1, 2, 3);
call、apply用途
继承
Javacript的继承方式有原型链继承、构造函数继承以及ES6引入的extends继承方法。构造函数方法通过调用父构造函数的call方法来实现继承。
function Animal () {
this.say = function () {
console.log('hello world');
}
}
function Cat () {
Animal.call(this); // or apply
}
let cat = new Cat();
cat.say(); // hello world
Cat构造函数创建的对象拥有从Animal构造函数继承的say()方法。
改变this指向
this指向一个对象,通常指向调用方法的执行环境所在的对象。this的指向在函数的执行环境动态绑定,与声明函数的环境无关。
var name = 'window';
function Animal (name) {
this.name = name
}
function Cat (name) {
Animal.call(this, name); // or apply
}
let sayName = function () {
console.log(this.name);
}
let dog = new Animal('哈士奇');
let cat = new Cat('波斯猫');
sayName.call(null); // window 非严格模式下null 或 undefined会指向全局(window)
sayName.call(dog); // 哈士奇
sayName.call(cat); // 波斯猫
匿名函数也常常用到call、apply。
var name = 'window';
(function () {
//
console.log(this.name);
}).call(window);
调用其他对象方法
使用call、apply调用其他方法时,如果不涉及this指向,call、apply对第一个参数没有限制。
例如找出数组里的最小值,将Math作为第一个参数,数组作为第二个参数。
let arr = [3, 1, 5];
let min = Math.min.apply(Math, arr);
// or Math.min.apply({}, arr); Math.min.apply(null, arr);
console.log(min); // 1