JavaScript——继承

js 中的继承是原型的继承,而不是改变构造函数的原型

1、继承是原型的继承

*通过设置__proto__实现继承

      function User() {}
      User.prototype.name = function () {
        console.log("user.name");
      };

      function Admin() {}
      Admin.prototype.__proto__ = User.prototype;
      Admin.prototype.role = function () {
        console.log("admin.role");
      };
      
      let a = new Admin();
      
      a.name(); //user.name
      m.role(); //user.name

*通过Object.create实现继承

      function User() {}
      User.prototype.name = function () {
        console.log("user.name");
      };

      function Admin() {}
      //将User的prototype作为原型生成一个新对象,再将其赋值给Admin的prototype
      Admin.prototype = Object.create(User.prototype);
      Admin.prototype.role = function () {
        console.log("admin.role");
      };
      
      let a = new Admin();
      a.name(); //user.name

2、继承对 constructor 属性的影响

        function User() { }

        User.prototype.name = function () {
            console.log('user.name');
        }

        function Admin() { }
        
        //继承User
        Admin.prototype = Object.create(User.prototype);
       
        Admin.prototype.role = function () {
            console.log('admin.role');
        }
        console.dir(Admin)//constructor 丢失
       

如下代码,a. __ proto __ 指向Admin.prototype ,但是Admin的prototype上没有constructor属性,所以就会延着原型链找到User.prototype的constructor,所以最后结果会输出 ture

        let a = new Admin();
        let b = new a.__proto__.constructor();
       
        console.dir(b.__proto__ === User.prototype)//true

解决:

        //继承User
        Admin.prototype = Object.create(User.prototype);
        //手动加上 constructor属性
        Admin.prototype.constructor = Admin;
        Admin.prototype.role = function () {
            console.log('admin.role');
        }

3、禁止 constructor 被遍历

        ...
        let a = new Admin();
        
        for (const key in a) {
            console.log(key);
        }

在这里插入图片描述
为什么会遍历出 constructor?

        ...
        //继承User
        Admin.prototype = Object.create(User.prototype);
        Admin.prototype.constructor = Admin;

        console.log(Object.getOwnPropertyDescriptors(Admin.prototype));

属性描述符 enumerable:表示可以遍历
在这里插入图片描述
解决:

        ...
        //继承User
        Admin.prototype = Object.create(User.prototype);
       //思路打开,换种方式继承
        Object.defineProperty(Admin.prototype, 'constructor', {
            value: Admin,
            enumerable: false
        })

4、方法重写与父级属性访问

        function User() { }

        User.prototype.show = function () {
            console.log('user.name');
        }

        User.prototype.site = function () {
            return 'hello'
        }

        function Admin() { }

        //继承User
        Admin.prototype = Object.create(User.prototype);
        Admin.prototype.constructor = Admin;

        //重写父类show方法
        Admin.prototype.show = function () {
           //父级属性访问
            console.log(User.prototype.site() + 'admin.show')
        }

        let a = new Admin();
        a.show();

5、面向对象的多态

        function User() { }
        User.prototype.show = function () {
            console.log(this.desc());
        }

        function Admin() { }
        Admin.prototype = Object.create(User.prototype)
        Admin.prototype.desc = function () {
            return 'admin'
        }

        function Member() { }
        Member.prototype = Object.create(User.prototype);
        Member.prototype.desc = function () {
            return 'member'
        }

        for (const obj of [new Admin(), new Member()]) {
            obj.show()
        }

6、使用父类构造函数初始属性

        function User(name, age) {
            this.name = name;
            this.age = age;
        }

        User.prototype.show = function () {
            console.log(this.name, this.age);
        };

        function Admin(...args) {
            User.apply(this, args);
            // User.call(this, name, age)
        }

        Admin.prototype = Object.create(User.prototype);

        let zs = new Admin('zs', 10);

        zs.show();

7、使用原型工厂封装继承

        //封装继承
        function extend(sub, sup) {
            sub.prototype = Object.create(sup.prototype);
            Object.defineProperty(sub.prototype, 'constructor', {
                value: sub,
                enumerable: false
            })
        }

        function User(name, age) {
            this.name = name;
            this.age = age;
        }
        User.prototype.show = function () {
            console.log(this.name, this.age);
        }

        function Admin(...args) {
            User.apply(this,args);
        }

        //继承
        extend(Admin, User);

        let admin = new Admin('张三', 19);

        admin.show();//张三 19

8、对象工厂派生对象并实现继承

        function User(name, age) {
            this.name = name;
            this.age = age;
        }

        User.prototype.show = function () {
            console.log(this.name, this.age);
        }

        function admin(name, age) {
            // 1.继承
            // const instance = {};
            // instance.__proto__ = User.prototype;

            // 2.继承
            const instance = Object.create(User.prototype);
            User.call(instance, name, age);

            instance.role = function () {
                console.log('role');
            }
            return instance;
        }

        let obj = admin('张三', 20);
        obj.role();

9、使用mixin实现多继承

        function extend(sub, sup) {
            sub.prototype = Object.create(sup.prototype);
            Object.defineProperty(sub.prototype, 'constructor', {
                value: sub,
                enumerable: false
            })
        }
        
        const Address = {
            getAddress() {
                console.log('获取地址');
            }
        }

        const Request = {
            ajax() {
                console.log('请求');
            }
        }
        function User(name, age) {
            this.name = name;
            this.age = age;
        }

        User.prototype.show = function () {
            console.log(this.name, this.age);
        }

        function Admin(name, age) {
            User.call(this, name, age)
        }
        //继承
        extend(Admin, User);
        Admin.prototype = Object.assign(Admin.prototype, Request,Address);

        let admin = new Admin('张三', 19);
        admin.ajax()
        admin.getAddress()

10、mixin内部继承与super关键字

        ...
        const Address = {
            __proto__: Request,
            getAddress() {
                console.log(super.ajax() + '获取地址');
            }
        }
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值