? ? ? 我们在项目中经常使用call或者apply来继承某个类的实例属性和方法。但是你知道两者的却区别是什么吗?了解两者的区别,有助于你正确的选择使用call还是apply。
? ? ? 在javascript中call方法和apply方法调用产生的效果是一样的,只是语法(参数)不一样。
目录:
? 1、call和apply的区别,然后实例演示
? 2、call和apply的常用应用场合
? 3、call和apply不能继承原型的属性和方法
? 4、怎样继承原型的属性和方法
?
1、call和apply的区别,然后实例演示
?call语法如下:
? ? ? obj.call(要替换的执行环境,参数1, 参数2,……,参数n);
?【实例】创建Person类,接收name和age两个参数及提供getName()和getAge()方法。然后创建一个Student对象从Person中继承name和age实例属性和方法。
// Person构造函数
function Person(name, age){
this.name = name;
this.age = age;
// 添加方法到原型
if (typeof Person.prototype.getName != "function") {
Person.prototype.getName = function(){
return this.name;
};
Person.prototype.getAge = function(){
return this.age;
}
}
}
// Student构造函数
function Student(name, stuNum, age, qq){
this.stuNum = stuNum;
this.qq = qq;
// 继承Person类的实例属性
Person.call(this, name, age);
}
var stu = new Student("administritor", "No.1001", 23, "1840554");
alert([stu.name, stu.age]); // 结果:administritor,23
?
apply语法如下:
? ? ? object.apply(要替换的执行环境,[参数1, 参数2,……,参数n ]);
?【实例】创建Person类,接收name和age两个参数及提供getName()和getAge()方法。然后创建一个Student对象从Person中继承name和age实例属性和方法。
// Person的构造函数
function Person(name, age){
this.name = name;
this.age = age;
// 添加方法到原型
if (typeof Person.prototype.getName != "function") {
Person.prototype.getName = function(){
return this.name;
};
Person.prototype.getAge = function(){
return this.age;
}
}
}
// Student的构造函数
function Student(name, stuNum, age, qq){
this.stuNum = stuNum;
this.qq = qq;
// 继承Person类的实例属性
Person.apply(this, [name, age]);
}
var stu = new Student("administritor", "No.1001", 23, "1840554");
alert([stu.name, stu.age]); // 结果:administritor,23
从上面实例可以看出,call和apply的主要区别是在指定调用object对象时传递构造参数的方式。call使用的类似java中的可变参数,即将构造参数一次排在“要替换的执行环境”后面。apply则使用一个数组将构造参数进行包装,然后传递。
?
2、call和apply的常用应用场合
【实例】如果Person对象的构造参数和Student对象的构造参数完全一样(包括顺序)。此时,我们应该选择call还是apply呢?由于apply接收一个数组、Person和Student的构造参数一样且arguments也是一个数组。则,我们可以直接用:object.apply(this, arguments);就可进行继承。但是有人说,call也可以啊。我直接将参数依次写在object.call(this, arg1, arg2,...,argn)。如果Person和Student的参数有n个,则你需要写多少呢,你能保证你不会把顺序写错,你觉得代码可读性好吗?因此,如果被继承和继承的构造函数一样(包括参数顺序),则推荐使用apply方式。
// Person构造函数
function Person(name, age){
this.name = name;
this.age = age;
// 添加方法到原型
if (typeof Person.prototype.getName != "function") {
Person.prototype.getName = function(){
return this.name;
};
Person.prototype.getAge = function(){
return this.age;
}
}
}
// Student构造函数
function Student(name, age){
// Person.apply(this, [name, age]);
// 同上
Person.apply(this, arguments);
if (typeof Student.prototype.setName != "function") {
Student.prototype.setName = function(name){
this.name = name;
};
Student.prototype.setAge = function(age){
this.age = age;
};
}
}
// 测试
var stu = new Student("administritor", 23);
alert([stu.name, stu.age]);
stu.setName("operation");
stu.setAge(41);
alert([stu.name, stu.age]);
如果Person和Student的参数不一样,则两种方式你就选择你自己喜欢的方式。
// Person构造函数
function Person(name, age){
this.name = name;
this.age = age;
}
// 方式一:
function Student(name, sex, age, email){
this.sex = sex;
this.email = email;
Person.call(this, naem, age);
}
方式二:
function Student(name, sex, age, email){
this.sex = sex;
this.email = email;
Person.apply(this, [name, age]);
}

