JS继承的几种方法

1)原型继承

        let Person = {
            eays: 2,
            head: 1
        }
        function Woman(){

        }
        Woman.prototype = Person
        Woman.prototype.constructor = Woman //由于给prototype重新赋值,需要让constructor重新指回原来的构造函数
        let one = new Woman
        console.log(one);
        console.log(one.eays);//2 继承了Person

        function Man(){

        }
        Man.prototype = Person
        let two = new Man
        console.log(two.head);//1 继承了Person

问题:我们给Woman添加方法,Man也会添加上

        let Person = {
            eays: 2,
            head: 1
        }
        function Woman(){

        }
        Woman.prototype = Person
        Woman.prototype.constructor = Woman //由于给prototype重新赋值,需要让constructor重新指回原来的构造函数
        Woman.prototype.boby = function(){
            console.log('宝贝');
        }
        let one = new Woman
        console.log(one);
        // console.log(one.eays);//2 继承了Person

        function Man(){

        }
        Man.prototype = Person
        let two = new Man
        console.log(two);
        // console.log(two.head);//1 继承了Person

 

 原因:他们原型都继承了Person,接收了同一个对象,根据引用类型的特点,他们指向同一个对象,修改一个就都会影响

解决方法:利用构造函数  (以下几种方法使用同一个例子(Person))

        function Person(){
            this.eays = 2
            this.head = 1
        }
        function Woman(){

        }
        Woman.prototype = new Person()  //每次new出来一个新的对象,结构一样,内容一样,对象不一样,就实现了更改一个而不影响另一个
        Woman.prototype.constructor = Woman //由于给prototype重新赋值,需要让constructor重新指回原来的构造函数
        Woman.prototype.boby = function(){
            console.log('宝贝');
        }
        let one = new Woman
        console.log(one);
        // console.log(one.eays);//2 继承了Person

        function Man(){

        }
        Man.prototype = new Person()    //同理
        Man.prototype.constructor = Man
        let two = new Man
        console.log(two);
        // console.log(two.head);//1 继承了Person

2)call、apply继承
        function Person(eays,head){
            this.eays = eays
            this.head = head
            this.Play = function(){
                console.log('玩');
            }
        }
        Person.prototype.eat = function () {
            console.log('麻辣烫');
        }


        function Student(eays,head,sex){
            //cal() 改变this指向,实现继承
            Person.call(this,eays,head,sex)
            // Person.apply(this,[eays,head,sex])
            this.sex = sex
        }
        Student.prototype.study = function(){
            console.log('学习');
        }
        let stu1 = new Student(2,1,'女')
        console.log(stu1);
        console.log(stu1.eays); //2
        console.log(stu1.sex);  //女
        stu1.study()            //学习
        stu1.eat()              //报错

call,apply继承【只能继承所有构造的属性和方法,不能继承原型的内容】

3)实例继承

        

        function Person(eays,head){
            this.eays = eays
            this.head = head
            this.Play = function(){
                console.log('玩');
            }
        }
        Person.prototype.eat = function () {
            console.log('麻辣烫');
        }


        function Student(eays,head,sex){
            let stu2 = new Person(eays,head)
            stu2.sex = sex
            return stu2
        }
        Student.prototype.study = function(){
            console.log('学习');
        }
        let stu1 = new Student(2,1,'女')
        console.log(stu1);
        console.log(stu1.eays); //2
        console.log(stu1.sex);  //女
        stu1.eat()              //麻辣烫
        stu1.study()            //报错,不能往Student原型上添加内容

由于return,当new Student(2,1,'女')的时候实际拿到的是Person,这样我们虽然可以用Person原型上的内容但是我们Student原型上的内容却不能用了,也就不能在往Student原型上添加内容了

4)拷贝继承
        function Person(eays,head){
            this.eays = eays
            this.head = head
            this.Play = function(){
                console.log('玩');
            }
        }
        Person.prototype.eat = function () {
            console.log('麻辣烫');
        }

        //拷贝继承
        function Student(eays,head,sex){
            let stu2 = new Person(eays,head)
            for( k in stu2){
                // console.log(stu2[k]);
                //遍历出来的东西添加到原型身上
                Student.prototype[k] = stu2[k]

            }
            this.sex = sex
            
        }
        Student.prototype.study = function(){
            console.log('学习');
        }
        let stu1 = new Student(2,1,'女')
        console.log(stu1);
        console.log(stu1.eays); //2
        console.log(stu1.sex);  //女
        stu1.eat()              //麻辣烫
        stu1.study()            //学习

和上面的方法类似,只不过弥补了上面的不足,利用拷贝继承,new Student(2,1,'女')的时候拿到的将是我们new出来的构造函数本身,也可以实现往Student原型上添加内容了

5)组合继承

        用构造继承方法(call)继承父级的普通属性和方法;

        用原型继承,继承父级的原型属性和方法

        重点:结合了两种模式的优点,传参和复用。

         特点: 1、可以继承父类原型上的属性,可以传参,可复用; 2、每个新实例引入的构造函数属性是私有的。

         缺点:调用了两次父类构造函数(耗内存),子类的构造函数会代替原型上的那个父类构造函数。

        function Person(eays,head){
            this.eays = eays
            this.head = head
            this.Play = function(){
                console.log('玩');
            }
        }
        Person.prototype.eat = function () {
            console.log('麻辣烫');
        }

        //组合继承
        function Student(eays,head,sex){
            Person.call(this,eays,head)
            this.sex = sex
            this.study = function(){
                console.log('学习');
            }
        }
        Student.prototype = new Person()
        let stu1 = new Student(2,1,'女')
        console.log(stu1);
        console.log(stu1.eays); //2
        stu1.study()            //学习
        stu1.eat()              //麻辣烫
6)寄生继承

        1, 融合了以上所有方式的优点         2, 实现复杂

        function Person(eays,head){
            this.eays = eays
            this.head = head
            this.Play = function(){
                console.log('玩');
            }
        }
        Person.prototype.eat = function () {
            console.log('麻辣烫');
        }

        //寄生继承
        function Student(eays,head,sex){
            Person.call(this,eays,head)
            this.sex = sex
            this.study = function(){
                console.log('学习');
            }
        }
        (function (){
            let Super = function(){ }
            Super.prototype = Person.prototype
            Student.prototype = new Super()
        })()
        let stu1 = new Student(2,1,'女')
        console.log(stu1);
        console.log(stu1.eays); //2
        console.log(stu1.sex);  //女
        stu1.eat()              //麻辣烫

和上面相对比,原型里面干干净净只有原型里面的东西,构造里面只有构造的内容

ES6中继承

        class User{
            constructor (name,age){
                this.name = name;
                this.age = age;
            }
        
            showName(){
                console.log(`my name is ${this.name}`);
            }
            showPass(){
                console.log(`my age is ${this.age}`);
            }
            
        }

        class Vip extends User{
            constructor(name,age,stuid){
                super(name,age)
                this.stuid = stuid
            }
            study(){
                console.log(this.name + '学习');
            }
            
        }

        let vip = new Vip('jack',20,1001)
        console.log(vip);
        vip.showPass()
        vip.study();

小案例

        

<body>
    <input type="color" id="color">
    <input type="button" id="btn" value="提交">
    <script>
        btn.onclick = function(){
            var val = color.value;
            val.getRGB();
        }
        String.prototype.getRGB = function(){
            let color1 = this.replace(/#/g,'')
            let a = parseInt(color1.substring(0,2),16);
            let b = parseInt(color1.substring(2,4),16);
            let c = parseInt(color1.substring(4),16);
            let rgb = `rgb(${a},${b},${c})`
            console.log(rgb);
        }
    </script>
</body>
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值