JS 继承的正确操作

首先,我们先要明白,JS里的继承,是对原型的继承,而不是改变构造函数的原型

那这句话到底是什么意思呢?让我们通过一个例子解释一下。

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

    Admin.prototype = User.prototype;
    let admin = new Admin();
    admin.name(); //user name

这里我们往User的原型对象中添加了一个name方法,而且我们的Admin函数也希望能调用到User原型对象下的name方法,因此这里我们把User的原型对象直接赋值给了Admin的原型对象,也就是说Admin的原型对象被替换成了User的原型对象。

这种方法乍一看好像是没有问题的,也能顺利使用到User原型对象上的方法。但是当我们有多个函数同时希望通用到User原型对象上的方法的时候,问题就来了。

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

当我们的Member构造函数和Admin的构造函数的原型对象都改为User的原型对象的时候,Member和Admin本身原型对象上的方法自然而然就添加到了User的原型对象中了,而当Member的方法名跟Admin的方法名相同的时候,就会出现覆盖的情况(后调用的方法覆盖前一个方法),就会导致其中一个函数的方法不可使。

比如说在我们生活中,张三继承了一笔财产,是在自己原有财产的基础上新增了一笔财产,而不是继承了财产之后原来的财产小时掉。

因此这种直接改变原型对象的方式不是继承!

那正确的做法是什么呢?

我们知道,我们的构造函数的原型对象的对象原型指向的都是Object,因此我们可以通过改变对象原型实现正确继承的方法。

方法一:

    function User() {}
    function Admin() {}
    function Member() {}
    Member.prototype.__proto__ = User.prototype;
    Admin.prototype.__proto__ = User.prototype;

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

方法二:

function User() {}
    function Admin() {}
    function Member() {}

    Member.prototype = Object.create(User.prototype);
    Object.defineProperty(Member.prototype, 'constructor', {
        value: Member,
        enumerable: false
    });
    Admin.prototype = Object.create(User.prototype);
    Object.defineProperty(Admin.prototype, 'constructor', {
        value: Admin,
        enumerable: false
    });

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

这两种方法均可以实现继承。

此时经过这样设置之后,我们的Member和Admin的原型对象的对象原型指向的就不再是Object了,而是User的原型对象。通过这种做法,我们能让Menber和Admin保留它们自身的方法,还能让他们都共用到User原型对象中的方法。这就是真正意义上的继承。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值