美文网首页
继承 继承

继承 继承

作者: nwzk41 | 来源:发表于2016-12-01 20:19 被阅读0次

属性拷贝

继承不单单能通过原型链实现,也能通过其他方式实现,属性拷贝就是其中一种方法。

通过属性拷贝也能实现继承
子对象会继承父对象原型链上所有的自身属性

函数代码在此:

function extend2(Child,Parent) {
            var c = Child.prototype;
            var p = Parent.prototype;

            // 循环遍历 Parent 中的属性,复制给 Child
            for (var i in p){
                c[i] = p [i];
            };
            // uber 属性实现子级能找到父级的属性
            Child.uber = Parent.prototype;
        }

此时创建父级子级的构造函数及对象,调用函数形成继承关系

function Person(){}
        Person.prototype.description = "人类";
        Person.prototype.age = 0;
        Person.prototype.hobby = ["权利","金钱"]
        Person.prototype.say = function(){
            return "我的年龄:" +this.age;
        }

        function Student(){}
        // 实现继承关系,调用函数
        extend2(Student,Person);
        // 此时不需要更改 construtor 属性
        Student.prototype.description = "学生";
        Student.prototype.age= 18;

        var stu = new Student();
        console.log(stu.description);//学生
        console.log(stu.say());//我的年龄:18
        stu.hobby.pop()
        console.log(stu.hobby);//["权利"]

        var per = new Person();
        console.log(per.description);//人类
        console.log(per.say());//我的年龄:0
        console.log(per.hobby);//["权利"]

此时实现了继承的效果,stu 能访问 per 的属性

如图所示:

属性拷贝2.png

注意:该方法只针对于基本数据类型有效,JS中对象的传递大多数都是引用传递,仅仅是传递对象的地址,子对象修改,父对象中也相应地会改变


对象之间的继承

到目前来说。我们都是通过构造函数实现的继承

其实,我们完全可以不使用构造函数就实现继承关系,直接使用对象完成继承关系的建立

函数代码如下:

function extend3(parent,child) {
            // 如果child参数传进来,就是外面有已知对象给 child 赋值,
            //如果没有 Child 参数传进来,函数会创建一个空对象并返回,此空对象继承自 parent
            child = child || {};
            for (var i in parent){
                child[i] = parent[i];
            }
            child.uber = parent;
            return child;
        }

现在我们直接创建父级子级对象,调用函数实现继承,代码如下:

var  per = { 
            description:"人类",
            age:0,
            hobby:["金钱","权利"],
            say:function(){
                return "我的年龄是:" +this.age;
            },
        }

        function Student(){}

        var stu = new Student();
        // 建立继承关系(让一个已知的对象继承自 per)
        extend3(per,stu);
        stu.description = "学生";
        console.log(stu.description);//学生
        console.log(stu.age);//0
        stu.hobby.pop();
        console.log(stu.hobby);//["金钱"]
        console.log(stu.say());//我的年龄是:0
        console.log(per.hobby);//["金钱"]
        // 子对象访问父对象属性
        console.log(stu.uber.description);//人类


        // 创建一个继承自 per的对象

        var t = extend3(per);
        console.log(t.description);
        console.log(t.say());

实现了子级继承父级的效果,同时,我们还能通过此函数直接创建子级对象


深拷贝

上面两种方式虽然都能调用函数,但是如果修改对象的值,是直接修改父级对象的值,原来父级的属性就被替换了

extend2 和 extend3 都是浅拷贝

深拷贝:内存拷贝,将内存完整的拷贝一份

浅拷贝:引用拷贝,只复制对象的地址

如果想实现深拷贝

1.我们会用hasOwnProperty() 方法判断该属性是否需要复制的
2.子对象不会影响到父对象中的属性值

实现深拷贝的函数代码如下:

function deepCopy(parent,child){
            child = child || {};
            // 遍历父对象属性
            for(var i in parent){
                // 判断自身属性
                if(parent.hasOwnProperty(i)){
                    // 判断自身属性
                    if(/*对象类型*/typeof parent[i] === "object"){
                        // 判断属性是否是数组
                        child[i] = Array.isArray(parent[i]) ? [] : {};
                        // 把 parent[i]里的属性赋值给child[i]里面去
                        deepCopy(parent[i],child[i]);
                    }else{
                    // 基本数据类型
                    child[i] = parent[i];
                    }
                }
            }
            // child.uber = parent;
            return child;
        }

这次直接创建对象看看效果

var  per = { 
            description:"人类",
            age:0,
            hobby:["金钱","权利"],
            say:function(){
                return "我的年龄是:" +this.age;
            },
        }

        //  t 继承自 per
        var t = deepCopy(per);
        // t.description = "学生";
        console.log(t.description);//人类
        console.log(per.description);//人类
        t.hobby.pop();
        console.log(t.hobby);//["金钱"]
        console.log(per.hobby);//["金钱", "权利"]

深浅拷贝的原理


深浅拷贝.png

t 如果不修改 description 属性默认继承父级属性,同时,t修改数组,对 per 的数组值没有影响


原型继承与属性拷贝的混合应用

原型继承和拷贝继承混用的方式,能将两个父对象的属性用不同的方式继承下来
先创建两个对象 per 和 base ,作为父对象
代码如下:

var  per = { 
            description:"人类",
            age:0,
            hobby:["金钱","权利"],
            say:function(){
                return "我的年龄是:" +this.age;
            },
        }

        var base = {
            name:"二雷",height:180,weight:100,
        }

混用函数代码如下:

function extend(p1,p2) {
            var child;
            var F = function(){};
            F.prototype = p1;
            child =  new F();

            for(var i in p2){
                child[i] = p2[i];
            }
            return child;
        }

创建子级,看一下效果:



var t = extend(per,base);
        console.log(t.name);//二雷
        console.log(t.hobby);//["金钱", "权利"]

实现了


多重继承

其实,n个对象的属性也可以通过函数实现继承于1个子对象中,也就是一个子对象能继承到那个对象的属性

要实现这个方法,需要使用函数的 arguments 属性

父级对象的创建:

// 能继承多个对象的属性,创建多个对象
        var per1 = {
            name:"二雷",
        }
        var per3 = {
            age:20,
        }
        var per5 = {
            height:180,name:"雷",
        }
        var per6 = {
            weight:100,
        }

继承函数的创建:

// arguments类似数组,它的属性是当前函数所街搜到的所有参数
        function muli(){
            var child = {};
            for(var i = 0;i<arguments.length;i++) {
                for(var j in arguments[i]){
                    child[j] = arguments[i][j];
                }
            }
            return child;
        }
        // 注意:如果父对象中存在相同的属性,参数后面对象中的属性会覆盖前面对象中的属性
        var t = muli(per1,per3,per5,per6);
        console.log(t)//Object age: 20 height: 180 name: "雷" weight: 100 __proto__: Object

这样新建的t对象就有其所有父级元素的属性了,集大成者

不过要注意的是,如果父级元素中有相同的属性,谁在后面输出谁的属性,不过前面的属性值就被覆盖了,在当前函数下,不能找回前面的同名属性值,可以通过设置 uber 将所有父级对象属性保存下来,需要时再去获取。

相关文章

  • 继承 继承

    属性拷贝 继承不单单能通过原型链实现,也能通过其他方式实现,属性拷贝就是其中一种方法。 通过属性拷贝也能实现继承子...

  • 继承(单继承,多继承)

    将共性的内容放在父类中,子类只需要关注自己特有的内容 python中所有的内容都是对象,所有的对象都直接或间接继承...

  • js继承方式

    类式继承 构造函数继承 组合继承 类式继承 + 构造函数继承 原型式继承 寄生式继承 寄生组合式继承 寄生式继承 ...

  • Python-学习之路-08 OOP -02

    单继承和多继承 单继承:每个类只能继承一个类 多继承:每个类可以继承多个类 单继承的多继承的优缺点 菱形继承/钻石...

  • 原型相关(二)

    1.继承 继承方式:接口继承(只继承方法签名)实现继承(继承实际的方法)ECMAScript只支持实现继承,并且主...

  • 继承

    继承的引入和概述 继承案例和继承的好处 继承的弊端 Java中继承的特点 继承的注意实现和什么时候使用继承 继承中...

  • Java面向对象三大特性之继承

    继承 一、继承的特点 Java只支持单继承单继承 多继承 单继承、多继承优缺点①单继承优点:提高了代码的复用性,让...

  • 7、面向对象的程序设计3(《JS高级》笔记)

    三、继承 许多OO语言都支持两种继承方式:接口继承和实现继承。接口继承只继承方法签名,而实现继承则继承实际方法。由...

  • 【重学前端】JavaScript中的继承

    JavaScript中继承主要分为六种:类式继承(原型链继承)、构造函数继承、组合继承、原型式继承、寄生式继承、寄...

  • js之继承

    文章主讲 JS 继承,包括原型链继承、构造函数继承、组合继承、寄生组合继承、原型式继承、 ES6 继承,以及 多继...

网友评论

      本文标题:继承 继承

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