继承 继承

属性拷贝

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

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

函数代码在此:

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 将所有父级对象属性保存下来,需要时再去获取。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,547评论 6 477
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,399评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,428评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,599评论 1 274
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,612评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,577评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,941评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,603评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,852评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,605评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,693评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,375评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,955评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,936评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,172评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 43,970评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,414评论 2 342

推荐阅读更多精彩内容

  • 博客内容:什么是面向对象为什么要面向对象面向对象编程的特性和原则理解对象属性创建对象继承 什么是面向对象 面向对象...
    _Dot912阅读 1,398评论 3 12
  • 1,javascript 基础知识 Array对象 Array对象属性 Arrray对象方法 Date对象 Dat...
    Yuann阅读 889评论 0 1
  • 交作业~ 教程地址:AI教程!手把手教你绘制复古风格的可爱卡通小狐狸
    豹猫抱着猫阅读 458评论 0 2
  • 努力奋斗,努力学习 1,早起,健康饮食 2健身 3,单片机学完第五章 4自控第三章 5英语20161 6,复习预习电工基
    天才宽宽阅读 174评论 0 1
  • 1、关于身体健康方面: (1)06:30开始完成晨跑10公里并坚持听《超级个体》(下雨除外,预计用时1小时)。 2...
    清风_bd61阅读 237评论 0 0