美文网首页
对象的继承

对象的继承

作者: Sanyekui | 来源:发表于2019-11-04 17:42 被阅读0次

JS 作为面向对象的弱类型的语言,继承是它非常强大的特征之一

JS继承实现的方式:

1.原型链继承
2.构造函数继承
3.实例继承
4.拷贝继承
5.组合继承和寄生继承

原型链继承:

核心:将父类的实例作为子类的原型

function Animal(name){//创建一个父类 Animals
    this.name = name;//属性
    this.sleep = function(){//方法
        return this.name+"在睡觉";
    }
}

//给父类 Animal 加一个原型方法:
Animal.prototype.eat = function(food){
    return this.name + "正在吃" + food;
}

//原型链继承核心: 将父类的实例作为子类的原型
function Cat(age){
    this.age = 12;
}//创建一个子类

Cat.prototype = new Animal();//把Animal父类的实例赋给子类的原型
//若子类需要新增属性和方法必须放在它的后边
Cat.prototype.name = "cat";
//给子类新增一个原型属性name 相当于是 Animal父类的 this.name = "cat"; 但不会影响父类
                        
Cat.prototype.run = function(){
    return this.name + this.age + this.sleep();
}               
var cat = new Cat();
console.log(cat.name);//cat 
console.log(cat.eat("fish"));//cat正在吃fish
console.log(cat.sleep());//cat在睡觉
console.log(cat instanceof Cat);//turn
console.log(cat instanceof Animal);//turn
console.log(cat.run());//cat12cat在睡觉

原型链继承的特点和缺点:
特点:

1.非常纯粹的继承关系,它实例既是子类的实例,也是父类的实例
2.父类新增的原型方法和属性,子类都是可以访问的到的
3.简单,方便

缺点:

1.如果子类要新增属性和方法,必须要放在new 父类()这2.样的语句之后执行
3.无法实现多继承的
4.来自原型的所有属性被所有实例所共享
5.创建子类实例时,无法向父类构造函数传参


构造函数的继承:

使用父类的构造函数来增强子类的实例,其实就是复制父类的实例属性给子类,不用到原型链

function Animal(name){//创建一个父类 Animals
    this.name = name;//属性
    this.sleep = function(){//方法
        return this.name+"在睡觉";
    }
}
function Dog(name){
    Animal.call(this);
//属性使用对象冒充,其实就是改变this指向,继承父类
//this 相当于 new Animal
    this.name = name;
    Cat.call(this);//可以实现多个父类继承
}
var dog = new Dog("dog");
console.log(dog.name);//dog
console.log(dog.sleep())//dog在睡觉
console.log(dog.name);//dog
console.log(dog.age);//12
            
//console.log(dog.eat("狗粮"));//无法访问父类原型对象上的方法
console.log(dog instanceof Dog);//ture
console.log(dog instanceof Animal);//false,不能继承父类的原型对象

构造函数继承的特点和缺点:
特点:

1.创建子类实例的时候,可以向父类传递参数
2.可以实现多个继承(call多个父类对象)

缺点:

1.实例是子类的实例,不是父类的实例
2.只能继承父类实例的属性和方法,不能继承父类的原型属性和方法
3.无法实现函数复用,每个子类都有父类实例函数的副本,影响性能


实例继承:

为父类的实例添加新的属性,作为子类实例的返回值

function Animal(name){//创建一个父类 Animals
    this.name = name;//属性
    this.sleep = function(){//方法
        return this.name+"在睡觉";
    }
}
//给父类 Animal 加一个原型方法:
Animal.prototype.eat = function(food){
    return this.name + "正在吃" + food;
}

function Sheep(name){
    var animal = new Animal();//把父类的实例赋给animal
    animal.name = name;//给实例添加属性 
    return animal;//返回属性值 作为子类的实例返回,但还是属于父类的实例
}
            
var sheep = new Sheep("Xiaoen");
//var sheep = Sheep("Xiaoen");
console.log(sheep.name);//Xiaoen
console.log(sheep.sleep());//Xiaoen在睡觉
console.log(sheep.eat("草"));//Xiaoen在吃草
console.log(sheep instanceof Sheep);//false
console.log(sheep instanceof Animal);//ture

实例继承的特点和缺点:

特点:
不限制调用方式,不管是new 子类()还是直接子类(),返回的对象都具有相同的效果

缺点:
实例是父类的实例,不是子类的实例
不支持多继承,因为函数的返回值只有一个


拷贝继承:(少用)

支持多继承,效率低,内存占用高(因为要拷贝父类的属性和方法)
没有办法获取父类不可枚举的方法(不可枚举的方法不能使用for in 遍历)


寄生组合继承:

核心:通过寄生方式,砍掉父类的实例属性,这样,在调用两次父类的构造函数时,
就不会初始化两次实例的方法和属性,避免了组合继承的缺点
核心:通过调用父类构造,继承父类的属性并且保留传参的优点,
然后通过将父类实例作为子类原型,实现函数复用

function Animal(name){//创建一个父类 Animals
    this.name = name;//属性
    this.sleep = function(){//方法
        return this.name+"在睡觉";
    }
}
function Rubbit(name){
    Animal.call(this);
    this.name = name;
}
Rubbit.prototype = new Animal();
Rubbit.prototype.constructor = Rubbit;//组合继承需要修复构造函数的指向
            
var rubbit = new Rubbit("小白兔");
console.log(rubbit.name);//小白兔
console.log(rubbit.sleep());//小白兔在睡觉
console.log(rubbit instanceof Rubbit);//true
console.log(rubbit instanceof Animal);//true

组合继承的特点和缺点:

特点:
实例既是父类的实例,也是子类的实例
可以继承实例的方法和属性,也可以继承原型的方法和属性
可以传参
函数可以重复使用

缺点:
调用了两次父类构造函数,生成了两份实例(子类的实例将子类原型的实例屏蔽掉了)


寄生组合继承:

核心:通过寄生方式,砍掉父类的实例属性,这样,在调用两次父类的构造函数时,
就不会初始化两次实例的方法和属性,避免了组合继承的缺点

function Animal(name){//创建一个父类 Animals
    this.name = name;//属性
    this.sleep = function(){//方法
        return this.name+"在睡觉";
    }
}
//给父类 Animal 加一个原型方法:
Animal.prototype.eat = function(food){
    return this.name + "正在吃" + food;
}

function Pig(name){
    Animal.call(this);
    this.name = name;
}
(function(){
    var obj = function(){}//创建一个没有实例方法的类
    obj.prototype = Animal.prototype;
    //将父类的原型传给这个没有实例方法的类的原型
    Pig.prototype = new obj();//将实例作为子类的原型
})();

Pig.prototype.constructor = Pig;//修复构造函数指向
            
var pig = new Pig('佩奇');
console.log(pig.name);//佩奇
console.log(pig.sleep());//佩奇在睡觉
console.log(pig.eat("垃圾"));//佩奇在吃垃圾
console.log(pig instanceof Pig);//true
console.log(pig instanceof Animal);//true

特点:完美

缺点:实现起来比较复杂

相关文章

  • javascript对象继承顺序、分类和内置Math对象

    javascript对象继承顺序、分类和内置Math对象 一、对象的继承顺序 所有对象都是从Object对象继承过...

  • 深入理解js中实现继承的原理和方法

    原型对象继承 ==原理:原型对象的属性可以经由对象实例访问== 下面的例子,所含【对象继承】和【构造函数继承】,用...

  • 对象的继承

    继承:prototype:原型对象,共享资源,每个函数对象都有 prototype 的显式属性proto:原型属性...

  • 对象的继承

    var obj={ name:"小兰", age:22, say:function(){ console.log(...

  • 对象的继承

    JS 作为面向对象的弱类型的语言,继承是它非常强大的特征之一 JS继承实现的方式: 1.原型链继承2.构造函数继承...

  • 对象的继承

    构造函数继承 让一个构造函数继承另一个构造函数,是非常常见的需求。这可以分成两步实现。第一步是在子类的构造函数中,...

  • 对象继承

    传统圣杯模式 YUI中的圣杯模式

  • 对象继承

    ES5继承:(1)通过原型或构造函数机制来实现。(2)先创建子类实例对象,然后让子类原型继承父类实例,从而获取到父...

  • java基础-day10-面向对象4.0

    面向对象4.0 1. 面向对象之继承 1.1 生活中的继承 1.2 Java中的继承 1.3 子类对象创建,会调...

  • JavaScript之面向对象编程

    五、面向对象编程 目录:面向对象原型继承、面向对象class继承(ES6引入的) 1.面向对象原型继承 类:模板 ...

网友评论

      本文标题:对象的继承

      本文链接:https://www.haomeiwen.com/subject/vjedbctx.html