call()
解读可参见:MDN-call()
apply()
解读可参见:MDN-apply()
每个函数都包含两个非继承而来的方法:apply()
和call()
。
call与apply都属于Function.prototype的一个方法,所以每个function实例都有call、apply属性。
作用
call()
方法和apply()
方法的作用相同:改变this指向
call()
、apply()
方法能劫持另外一个对象的方法,继承另外一个对象的属性
call()
obj1.(method).call(obj2,argument1,argument2)
如上,call()
的作用就是把obj1的方法放到obj2上使用,后面的argument1…这些做为参数传入。
function add (x, y)
{
console.log (x + y);
}
function minus (x, y)
{
console.log (x - y);
}
add.call (minus , 1, 1); //2
这个例子中的意思就是用 add 来替换 minus ,add.call(minus ,1,1) == add(1,1) ,所以运行结果为:console.log (2); // 注意:js 中的函数其实是对象,函数名是对 Function 对象的引用。
A.call(B,x,y)
就是把A的函数放到B中运行,x 和 y 是A方法的参数。
用call()
来实现继承,用this可以继承myfunc1中的所有方法和属性。
function myfunc1(){
this.name = 'Lee';
this.myTxt = function(txt) {
console.log( 'i am',txt );
}
}
function myfunc2(){
myfunc1.call(this);
}
var myfunc3 = new myfunc2();
myfunc3.myTxt('Geing'); // i am Geing
console.log (myfunc3.name); // Lee
apply()
func.apply(thisArg, [argsArray])
thisArg对象将代替func里this对象。如果 argArray 不是一个有效的数组或者不是 arguments 对象(类数组对象),那么将导致一个 TypeError。
argArray数组里的元素将作为单独的参数传给 func 函数。如果没有提供 argsArray 和 thisArg 任何一个参数,那么 Global 对象将被用作 thisArg , 并且无法被传递任何参数。
function Person(name,age)
{
this.name=name;
this.age=age;
}
function Student(name,age,grade)
{
Person.apply(this,arguments);
this.grade=grade;
}
var student=new Student("zhangsan",21,"一年级");
console.log(student.name+"-"+student.age+"-"+student.grade);//zhangsan-21-一年级
分析:Person.apply(this,arguments);
用构造器调用函数,this就是当前对象本身,此时代表的是Student。
arguments是类数组对象,此时是[“zhangsan”,21,“一年级”]。
最后去执行Person里面的内容。
apply的妙用: 可以将一个数组默认的转换为一个参数列表([param1,param2,param3]
转换为 param1,param2,param3
)
用 apply()
将数组添加到另一个数组
var array = ['a', 'b'];
var elements = [0, 1, 2];
array.push.apply(array, elements);//与下区别?prototype 原型
//Array.prototype.push.apply(array,elements);
console.info(array); // ["a", "b", 0, 1, 2]
//这里如果直接push()的话,是直接将elements数组添加到array中,而不是将元素添加进去
array.push(elements);
console.info(array);//["a", "b", [0, 1, 2]]
使用 apply()
和内置函数
/* 找出数组中最大/小的数字 */
var numbers = [5, 6, 2, 3, 7];
/* 应用(apply) Math.min/Math.max 内置函数完成 */
var max = Math.max.apply(null, numbers); /* 基本等同于 Math.max(numbers[0], ...) 或 Math.max(5, 6, ..) */
var min = Math.min.apply(null, numbers);
/* 代码对比: 用简单循环完成 */
max = -Infinity, min = +Infinity;
for (var i = 0; i < numbers.length; i++) {
if (numbers[i] > max)
max = numbers[i];
if (numbers[i] < min)
min = numbers[i];
}
注:JavaScript引擎的参数个数有限制(JavaScript 核心中已经做了硬编码 参数个数限制在65536),不同的JavaScript引擎有差异,超出限制会导致参数丢失。
apply 和call 是可以实现继承和多重继承
继承
function Animal(name,age){
this.name = name;
this.age = age;
this.showName = function(){
alert(this.name);
}
this.showAge = function(){
alert(this.age);
}
}
function Cat1(name,age){
Animal.call(this, name,age);
}
function Cat2(name,age){
Animal.apply(this,arguments);
}
var cat1 = new Cat1("Black Cat1","1");
var cat2 = new Cat2("Black Cat2");
cat1.showName();
cat2.showName();
Animal.call(this) 与Animal.apply(this) 的意思就是使用 Animal对象代替this对象,那么 Cat1,Cat2中不就有Animal的所有属性和方法了吗,Cat1,Cat2 对象就能够直接调用Animal的方法以及属性了。
多重继承
function Class10(){
this.showSub = function(a,b){
alert(a-b);
}
}
function Class11(){
this.showAdd = function(a,b) {
alert(a+b);
}
}
function Class2() {
Class10.call(this);
Class11.call(this);
}
function Class3() {
Class10.apply(this);
Class11.apply(this);
}
call()与apply()区别
他们的区别在于接收参数的方式不同:
call()
:第一个参数是this值没有变化,变化的是其余参数都直接传递给函数。在使用call()
方法时,传递给函数的参数必须逐个列举出来。
apply()
:传递给函数的是参数数组
function add(c, d){
return this.a + this.b + c + d;
}
var zzz = {a:1, b:3};
add.call(zzz, 5, 7); // 1 + 3 + 5 + 7 = 16
add.apply(zzz, [10, 20]); // 1 + 3 + 10 + 20 = 34