由于js
不像java
那样是真正面向对象的语言,js
是基于对象的,它没有类的概念。所以,要想实现继承,可以用js
的原型prototype机制或者用apply
和call
方法去实现
1.原型链继承
//定义父类
function Parent(){
this.name = 'mike';
}
//给父类添加原型属性
Parent.prototype.sex="male";
//定义子类
function Child(){
this.age = 12;
}
//将父类的新实例赋值给构造函数的原型
Child.prototype = new Parent();//Child继承Parent,通过原型,形成链条
var test = new Child();
alert(test.age);//12
alert(test.name);//mike
alert(test.sex);//male
//继续原型链继承
function Brother(){ //brother构造
this.weight = 60;
}
Brother.prototype = new Child();//继续原型链继承
var brother = new Brother();
alert(brother.name);//继承了Parent和Child,弹出mike
alert(brother.age);//弹出12
alert(brother.sex);//弹出male
alert(brother.weight );//弹出60
所有的构造函数都继承自Object
。而继承Object
是自动完成的,并不需要我们自己手动继承。
特点:1、实例可继承的属性有:实例的构造函数的属性,父类构造函数属性,父类原型的属性。(新实例不会继承父类实例的属性!)
缺点:1、新实例无法向父类构造函数传参。
2、继承单一。
3、所有新实例都会共享父类实例的属性。(原型上的属性是共享的,一个实例修改了原型属性,另一个实例的原型属性也会被修改!)
2.确定原型和实例的关系
可以通过两种方式来确定原型和实例之间的关系。操作符instanceof
和isPrototypeof()
方法
alert(brother instanceof Object)//true
alert(test instanceof Brother);//false,test 是brother的超类
alert(brother instanceof Child);//true
alert(brother instanceof Parent);//true
只要是原型链中出现过的原型,都可以说是该原型链派生的实例的原型,因此,
isPrototypeof()
方法也会返回true
在js
中,被继承的函数称为超类型(父类,基类也行),继承的函数称为子类型(子类,派生类)。
3.类式继承(借用构造函数)
<script>
function Parent(age){
this.name = ['mike','jack','smith'];
this.age = age;
}
function Child(age){
//用.call()和.apply()将父类构造函数引入子类函数(在子类函数中做了父类函数的自执行(复制))
Parent.call(this,age);
}
var test = new Child(21);
alert(test.age);//21
alert(test.name);//mike,jack,smith
test.name.push('bill');
alert(test.name);//mike,jack,smith,bill
</script>
特点:1、只继承了父类构造函数的属性,没有继承父类原型的属性。
2、解决了原型链继承缺点1、2、3。
3、可以继承多个构造函数属性(call多个)。
4、在子实例中可向父实例传参。
缺点:1、只能继承父类构造函数的属性。
2、无法实现构造函数的复用。(每次用每次都要重新调用)
3、每个新实例都有父类构造函数的副本,臃肿。
4.组合继承(原型链继承和借用构造函数继承)
<script>
function Parent(age){
this.name = ['mike','jack','smith'];
this.age = age;
}
Parent.prototype.run = function () {
return this.name + ' are both' + this.age;
};
function Child(age){
Parent.call(this,age);//对象冒充,给超类型传参
}
Child.prototype = new Parent();//原型链继承
var test = new Child(21);//写new Parent(21)也行
alert(test.run());//mike,jack,smith are both21
</script>
组合式继承是比较常用的一种继承方法,其背后的思路是 使用原型链实现对原型属性和方法的继承,而通过借用构造函数来实现对实例属性的继承。这样,既通过在原型上定义方法实现了函数复用,又保证每个实例都有它自己的属性。
<script>
function SuperType(name) {
this.name = name;
}
SuperType.prototype.sayName = function () {
alert(this.name);
};
function SubType(name, age) {
SuperType.call(this, name);
this.age = age;
}
SubType.prototype = new SuperType();
SubType.prototype.sayAge = function () {
alert(this.age);
};
var instance1 = new SubType("Nicholas", 29);
instance1.sayName();//Nicholas
instance1.sayAge();//29
var instance2 = new SubType("Greg", 27);
instance2.sayName();//Greg
instance2.sayAge();//27
</script>