- 所有的对象默认继承的都是Object这个类。
- 要实现继承,首先得需要一个父类。
一、原型链继承
<script>
function Animal(name,sex){
this.name = name||'Animal';
this.sex = sex||'未知';
this.sleep = function(){
console.log(this.name + "在睡觉!");
}
}
Animal.prototype = {
eat:function(){
console.log(this.name + "在吃饭!");
},
play:function(){
console.log(this.name + "在玩!");
}
}
function Cat(){
}
Cat.prototype = new Animal();
Cat.prototype.name = "小赵";
Cat.prototype.sex = "女";
var scat = new Cat();
console.log(scat);
scat.sleep();
scat.eat();
scat.play();
</script>
- instanceof属性—判断对象是否为某个类的实例。
- 子类对象的实例既是本身,也是父类。
console.log(scat instanceof Animal);
console.log(scat instanceof Cat);
- 原型链继承的优点:
- 1.子类对象的实例既是本身,也是父类。
- 2.父类新增的方法和属性,子类对象都可以访问。
- 原型链继承的缺点:
- 1.要想给子类新增属性和方法,必须在new(实例化)之后,或者直接写在子类里面。
- 2.不能实现多继承。因为父类的实例要给到子类的原型对象上面,若是有两个父类,那么后一个父类的实例会覆盖前一个父类的实例。
- 3.在子类的实例上不能直接向父类传递参数。
function Animal(name,age){
this.name=name||"";
this.age=age||"";
this.eat=function(){
console.log("吃饭");
};
this.sleep=function(){
console.log("睡觉");
}
}
Animal.prototype={
constructor:Animal,
play:function(){
console.log("玩");
}
}
function Type(type){
this.type=type||"";
}
function Dog(){
}
Dog.prototype=new Animal('小赵',21);
Dog.prototype=new Type("人类");
var dog=new Dog();
console.log(dog);
console.log(dog.name);
console.log(dog instanceof Dog);
console.log(dog instanceof Animal);
二、构造继承(call和apply继承)
- 核心原理:
- 使用父类的构造函数来增强子类,相当于复制父类的构造属性给子类(父类的原型复制不到)
<script>
function Animal(name,sex){
this.name = name||'Animal';
this.sex = sex||'未知';
this.sleep = function(){
console.log(this.name + "在睡觉!");
}
}
Animal.prototype = {
eat:function(){
console.log(this.name + "在吃饭!");
},
play:function(){
console.log(this.name + "在玩!");
}
}
function Type(type){
this.type = type||'类型';
}
Type.prototype.paTree = function(args){
console.log(args);
}
function Cat(name,sex,type){
Animal.call(this,name,sex);
Type.call(this,type);
}
var cat = new Cat('小猫','公','猫科');
cat.sleep();
console.log(cat);
</script>
console.log(cat instanceof Cat);
console.log(cat instanceof Animal);
console.log(cat instanceof Type);
- 构造继承的优点:
- 1.创建子类的时候可以向父类传递参数。
- 2.可以实现多继承。
- 构造继承的缺点:
- 1.子类对象的实例是本身,不是父类。
- 2.只能继承父类的构造属性和方法,不能继承原型对象上的属性和方法。
- 3.不是完全的继承,类似克隆父类的副本,影响性能。
三、实例继承
<script>
function Animal(name,sex){
this.name = name||'Animal';
this.sex = sex||'未知';
this.sleep = function(){
console.log(this.name + "在睡觉!");
}
}
Animal.prototype = {
eat:function(){
console.log(this.name + "在吃饭!");
},
play:function(){
console.log(this.name + "在玩!");
}
}
function Mouse(){
var animal = new Animal();
return animal;
}
var mouse = new Mouse();
console.log(mouse);
</script>
console.log(mouse instanceof Mouse);
console.log(mouse instanceof Animal);
- 实例继承的优点:
- 1.不限制调用方式(不管你是new,还是直接调用函数执行都可以)。
- 2.实例继承可以使用父类的构造属性,也可以使用父类的原型属性。
- 实例继承的缺点:
- 不支持多继承。
四、组合继承(将原型链继承和构造继承联合使用)
function Animal(name){
this.name=name||"";
this.eat=function(){
console.log("吃饭");
}
}
Animal.prototype={
sleep:function(){
return "睡觉";
}
}
function Cat(name){
Animal.call(this,name);
}
Cat.prototype=new Animal();
var cat=new Cat("小赵");
console.log(cat);
console.log(cat.name);
console.log(cat.sleep());
- 输出的名字从外向里
- 子类对象的实例既是本身,也是父类。
console.log(cat instanceof Animal);
console.log(cat instanceof Cat);
- 组合继承的优点:
- 原型链继承和构造继承相互弥补缺点。
- 组合继承的缺点:
- 组合继承里面存在两个实例,消耗内存。
五、寄生继承(将原型链继承和实例继承联合使用)
<script>
function Person(name,age){
this.name = name;
this.age = age;
}
Person.prototype = {
sleep:function(){
console.log(this.name + "在睡觉!");
}
}
function Student(obj){
function fun(){
}
fun.prototype = obj;
return new fun();
}
var p = new Person('小赵',18);
function getObj(){
var stu = Student(p);
stu.work = "学习";
return stu;
}
var s = getObj();
console.log(s);
console.log(s.work);
s.sleep();
console.log(s instanceof Person);
console.log(s instanceof Student);
</script>
- 寄生继承的优点:
- 没有创建自定义对象,因为只是套了个壳子返回对象,
- 寄生继承的缺点:
- 没用到原型,无法复用。