JavaScript几种常见的继承方法
Posted ourener
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了JavaScript几种常见的继承方法相关的知识,希望对你有一定的参考价值。
1、call() 方法
call() 方法是与经典的对象冒充方法最相似的方法。它的第一个参数用作 this 的对象。其他参数都直接传递给函数自身
function Huster(name,idNum,college) { this.name = name; this.idNum = idNum; this.college = college; this.course = new Array(); this.addCourse = function(course)//这个方法不能用prototype来定义,如果用的话,子类无法继承该方法 { //用原型prototype定义的方法可以用原型链来继承,call()方法和apply()方法都无法继承 this.course.push(course); console.log(this.course); }; } function Autoer(name,idNum) { this.college = ‘自动化‘; Huster.call(this,name,idNum,this.college);//Autoer使用call()方法来继承 Huster
if (typeof Autoer._initialized == "undefined")
{
Autoer.prototype.sayHobby = function() //自己的方法可以用原型链prototype定义
{
alert(this.college+‘人喜欢撸代码!‘);
};
Autoer._initialized = true;
}
}
var autoer1 = new Autoer(‘偶人儿‘,‘U123456789‘); //声明一个实例autoer1
console.log(autoer1.name,autoer1.idNum,autoer1.college,autoer1.course);
autoer1.addCourse(‘logistics‘);//调用Huster的方法
autoer1.sayHobby(); //调用自身的方法
2、apply() 方法
apply() 方法与call()方法几乎一样,唯一的区别就是apply()方法只有两个参数,第一个用作 this 的对象,第二个是要传递给函数的参数的数组。也就是说apply()方法把call()方法的若干个参数放到一个数组里,传递给父类
function Huster(name,idNum,college) { this.name = name; this.idNum = idNum; this.college = college; this.course = new Array(); this.addCourse = function(course)//这个方法不能用prototype来定义,如果用的话,子类无法继承该方法 { //用原型prototype定义的方法可以用原型链来继承,call()方法和apply()方法都无法继承 this.course.push(course); console.log(this.course); }; } function Autoer(name,idNum) { this.college = ‘自动化‘; Huster.apply(this,new Array(name,idNum,this.college));//Autoer使用apply()方法来继承 Huster if (typeof Autoer._initialized == "undefined") { Autoer.prototype.sayHobby = function() //自己的方法可以用原型链prototype定义 { alert(this.college+‘人喜欢撸代码!‘); }; Autoer._initialized = true; } } var autoer1 = new Autoer(‘偶人儿‘,‘U123456789‘); //声明一个实例autoer1 console.log(autoer1.name,autoer1.idNum,autoer1.college,autoer1.course); autoer1.addCourse(‘logistics‘);//调用Huster的方法 autoer1.sayHobby(); //调用自身的方法
3、原型链法(prototype chaining)
当父类的属性或方法是用原型链定义的时候,子类要用原型链法进行继承,因为父类的属性和方法是在父类的原型上面,如果用call()或者apply()方法的话,访问不到父类的属性和方法,并会报出Uncaught TypeError错误:Uncaught TypeError: autoer1.addCourse(所调用的父类的方法) is not a function;如果是属性的话,则显示undefined
下面是使用原型法继承的例子(来源于w3school教程http://www.w3school.com.cn/js/pro_js_inheritance_implementing.asp)
function ClassA() { } ClassA.prototype.color = "blue"; ClassA.prototype.sayColor = function () { alert(this.color); }; function ClassB() { } ClassB.prototype = new ClassA();
ClassB.prototype.name = ""; ClassB.prototype.sayName = function () { alert(this.name); };
var objA = new ClassA(); var objB = new ClassB(); objA.color = "blue"; objB.color = "red"; objB.name = "John"; objA.sayColor(); objB.sayColor(); objB.sayName();
注意:调用 ClassA 的构造函数,没有给它传递参数。这在原型链中是标准做法。要确保构造函数没有任何参数。
子类的所有属性和方法都必须出现在 prototype 属性被赋值后,因为在它之前赋值的所有方法都会被删除。为什么?因为 prototype 属性被替换成了新对象,添加了新方法的原始对象将被销毁。
此外,在原型链中,instanceof 运算符的运行方式也很独特。对 ClassB 的所有实例,instanceof 为 ClassA 和 ClassB 都返回 true。例如:
var objB = new ClassB(); alert(objB instanceof ClassA); //输出 "true" alert(objB instanceof ClassB); //输出 "true"
原型链的弊端是不支持多重继承。记住,原型链会用另一类型的对象重写类的 prototype 属性。
4、混合方式
这种继承方式使用构造函数定义类,并非使用任何原型。对象冒充的主要问题是必须使用构造函数方式,这不是最好的选择。不过如果使用原型链,就无法使用带参数的构造函数了。开发者如何选择呢?答案很简单,两者都用。
在前一章,我们曾经讲解过创建类的最好方式是用构造函数定义属性,用原型定义方法。这种方式同样适用于继承机制,用对象冒充继承构造函数的属性,用原型链继承 prototype 对象的方法。用这两种方式重写前面的例子,代码如下:
function Huster(name,idNum,college) { this.name = name; this.idNum = idNum; this.college = college; this.course = new Array(); if (typeof Autoer._initialized == "undefined") //动态原型法定义addCourse()方法 { Huster.prototype.addCourse = function(course) { this.course.push(course); console.log(this.course); }; } } function Autoer(name,idNum) { this.college = ‘自动化‘; Huster.call(this,name,idNum,this.college);//使用call()方法继承Huster的属性 if (typeof Autoer._initialized == "undefined") { Autoer.prototype.sayHobby = function() { alert(this.college+‘人喜欢撸代码!‘); }; Autoer._initialized = true; } } Autoer.prototype = new Huster(this.name);//使用原型法继承Huster的方法 var autoer1 = new Autoer(‘偶人儿‘,‘U123456789‘); autoer1.addCourse(‘logistics‘); console.log(autoer1.name,autoer1.idNum,autoer1.college,autoer1.course); autoer1.sayHobby();
在此例子中,继承机制由两行突出显示的红色代码实现。在第一行突出显示的代码中,在Autoer()构造函数中,用call()方法继承 Huster 类的 idNum、college、course 属性。在第二行突出显示的代码中,用原型链继承 Huster类的方法。由于这种混合方式使用了原型链,所以 instanceof 运算符仍能正确运行。
以上是关于JavaScript几种常见的继承方法的主要内容,如果未能解决你的问题,请参考以下文章