JavaScript继承的五种方式

一.原型链继承

特点:
1.子类的实例即是本身也是父类。
2.父类新增的原型方法和属性,子类对象都可以访问。

缺点:
1.子类添加属性和方法必须写在new之后或者直接写在子类里面。
2.不能实现多继承。
3.子类的实例不能直接向父类传递参。

示例代码:

<!DOCTYPE html>
<html>
<head lang="en">
    <meta charset="UTF-8">
    <title>
        <!--
        特点:
        1.子类的实例即是本身也是父类
        2.父类新增的原型方法和属性,子类对象都可以访问
        缺点:
        1.子类添加属性和方法必须写在new之后或者直接写在子类里面
        2.不能实现多继承
        3.子类的实例不能直接向父类传递参-->
    </title>
</head>
<body>
    <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 = new Animal();
        Cat.prototype.name = "阿狸";
        Cat.prototype.sex = "男";
        /*子类的实例对象(不能直接向父类传递参数)*/
        var scat = new Cat();
        scat.name = '桃子';
        scat.sex = '女';
        console.log(scat);
        scat.sleep();
        scat.eat();
        scat.play();
        console.log(scat instanceof Animal);//true,即子类的实例是父类(instanceof:用来测试一个对象是否为一个类的实例)
        console.log(scat instanceof Cat);//true,即子类的实例是本身
    </script>
</body>
</html>

二.构造继承

特点:
1.创建子类的时候可以向父类传递参数。
2.可以实现多继承。

缺点:
1.子类对象的实例是本身而不是父类。
2.只能继承父类的构造属性和方法,不能继承原型属性和方法。
3.不是完全的继承,类似克隆父类的副本。

示例代码:

<!DOCTYPE html>
<html>
<head lang="en">
    <meta charset="UTF-8">
    <title>
        <!--
        特点:
        1.创建子类的时候可以向父类传递参数。
        2.可以实现多继承。
        缺点:
        1.子类对象的实例是本身而不是父类。
        2.只能继承父类的构造属性和方法,不能继承原型属性和方法。
        3.不是完全的继承,类似克隆父类的副本。-->
    </title>
</head>
<body>
    <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);
        console.log(cat instanceof Cat);//true
        console.log(cat in Animal);//false
        console.log(cat instanceof Type);//false
    </script>
</body>
</html>

三.实例继承

特点:
1.不限制调用方式:可以new也可以直接调用函数执行。

缺点:
1.不支持多继承。

示例代码:

<!DOCTYPE html>
<html>
<head lang="en">
    <meta charset="UTF-8">
    <title>
        <!--
        优点:
        1.不限制调用方式:可以new也可以直接调用函数执行。
        缺点:
        1.不支持多继承。-->
    </title>
</head>
<body>
    <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);
        console.log(mouse instanceof Mouse);//false
        console.log(mouse instanceof Animal);//true
    </script>
</body>
</html>

四.组合继承

特点:
1.原型链继承和构造继承相互弥补缺点。

缺点:
1.里面存在两个实例消耗内存。

示例代码:

<!DOCTYPE html>
<html>
<head lang="en">
    <meta charset="UTF-8">
    <title>
        <!--
        特点:
        1.原型链继承和构造继承相互弥补缺点。
        缺点:
        1.里面存在两个实例消耗内存。-->
    </title>
</head>
<body>
<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(name,sex){
        Animal.call(this,name,sex);//构造继承
    }
    Cat.prototype=new Animal();//原型链继承
    var cat=new Cat('阿狸','男');
    console.log(cat);
    cat.eat();
    console.log(cat instanceof Animal);//true
    console.log(cat instanceof  Cat);//true
</script>
</body>
</html>

五.寄生继承

特点:
1.没有创建自定义类型,只是套了个壳子返回对象,这个函数即为创建的新对象。

缺点:
1.没有用到原型,无法复用。

示例代码:

<!DOCTYPE html>
<html>
<head lang="en">
    <meta charset="UTF-8">
    <title></title>
</head>
<body>
    <script>
        function Person(name, age) {
            this.name = name;
            this.age = age;
        }
        Person.prototype = {
            sleep: function () {
                console.log(this.name + "在睡觉!");
            }
        };
        var p = new Person('小明', 18);//实例化person

        function Student(obj) {
            function fun() {
            }
            fun.prototype = obj;//寄生在fun函数的原型对象上面
            return new fun();
        }

        function getObj() {
            var stu = Student(p);
            stu.work = "学习";
            return stu;
        }
        var s = getObj();
        console.log(s);
        s.sleep();
    </script>
</body>
</html>
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值