• 原型继承+原型链 + 对象继承发展


    一、原型继承:

      1、说起原型继承,就要先由构造函数创造对象说起,首先了解构造函数内部基本原理:

          (1).在函数体最前面隐式的加上this = {}

          (2).执行 this.xxx = xxx;

          (3).隐式的返回this

        并且要注意隐士创建的this对象中有个名为__proto__的属性,其属性值为该构造函数继承的原型prototype。

        而原型对象的有一个名为constructor的属性,其属性值为继承之的构造函数,

        所以可以通过这两个属性相互查看

      2.原型的定义及一些特点:

        a.定义:原型是function对象的一个属性,它定义了构造函数制造出的对象的公共祖先。通过该构造函数产生的对象,可以继承该原型的属性和方法。原型也是对象。

        b.利用原型特点和概念,可以提取共有属性。

        c.对象如何查看原型 — > 隐式属性 __proto__

        d.对象如何查看对象的构造函数 — > constructor

      3、若一个构造函数没有指定其原型,则其原型默认为Object.prototype

    二、原型链:

      1.原型的形成,最好的解释就是代码了,看如下代码即可

      

    A.protorype = {
            name: 'a'
        }
        function A() (
            this.name = 'A';
        )
        B.prototype = new A();
        function B() {
            this.name = 'B';
        }
        C.prototype = new B();
        function C(){
            this.name = 'C';
        }
        C继承B,B继承A,形成C->B->A的一条以原型为继承方式的原型链

      2、原型链上属性的增删改查:

        (1)查:优先去实例对象上寻找是否有该属性,若没有,则再去其对应的原型上去寻找该属性,若都没有,则返回undefined

        (2)增:直接给实例对象增添属性,则仅仅在实例对象上增添属性,若在原型上增添属性,则在原型上增添属属性,则在原型上增添属性,其实例继承原型增添的属性。

        (3)删:delete仅仅能删除实例对象的属性,即构造函数原有的自己的属性和后来实例对象增添的属性,还有关于delete的一点需注意,delete无法删除原型的属性和用var定义的变量(即非window的属性)

          (4)改:更改实例对象的属性,则仅仅更改实例对象的属性值;更改原型的属性值,则更改原型的属性值,继承该原型的对象对应属性值也会被更改;

    三、对象继承的发展:

      1、传统模式:即正常的通过构造函数创建实例对象,来继承原型

        缺点:继承了过多不必要的属性

      2、借用其他构造函数(即通过call / apply来改变构造函数内this对象的引用)

        缺点:无法继承借用构造函数的原型

        

      A.prototype = {
            name: 'a',
            age: 18,
            class: 1
        }
        function A(){
            this.name = 'A';
        }
        function B(){
            A.call(this);
        }
        var b = new B();
        console.log(b.name); // A
        console.log(b.age) // undefined

      3、共享原型:即将其他构造函数的原型直接赋值给本构造函数的原型

        缺点:两个原型会想回影响,更改其中一个原型,更一个对应的原型也会被更改。

      

      A.prototype = {
            name: 'a',
            age: 18,
            class: 1
        }
        function A(){
            this.name = 'A';
        }
        B.prototype = A.prototype;
        function B(){
            this.name = 'B';
        }
      C.prototype = A.prototype;
      function C() {
        this.name = "C";
      }
    var a = new A(); var b = new B();
    var c = new C(); console.log(a.age);
    // 18 console.log(b.age); //18
    console.log(c.age); //18

    // 原型继承成功 B.prototype.age = 20; //更改其中一个原型的age属性 console.log(b.age);//20 console.log(c.age); //20 // 继承A原型的B和C相互影响

      4、圣杯模式:

         每次继承的都是新创建的F构造函数实例,相互之间不会影响。其实此处针对F形成了闭包,Child引用了F,导致F不会销毁。

        (1)正常函数形式:

        

      function inherit (Child, Parent) {
            // 借用F这个中间量来继承,而不是直接共享原型
            var F = function (){}
            F.prototype = Parent.prototype;
            Child.prototype = new F();
            // 自定义构造函数原型时,同时要更正自定义原型的constructor,否则一般默认为Object(),次函数若不指定constructor,则constructor为Parent
            Child.prototype.constructor = Child; 
            
            Child.prototype.uber = Parent; //记录真正继承的是谁
        }

        (2)闭包形式:

        

        var inherit = (function(){
            var F = function (){};
            return function (Child, Parent) {
                F.prototype = Parent.prototype;
                Child.prototype = new F();
                Child.prototype.constructor = Child;
                Child.prototype.uber = Parent;
            }
        })();
  • 相关阅读:
    BZOJ2243: [SDOI2011]染色(树链剖分/LCT)
    BZOJ2157: 旅游(LCT)
    BZOJ3510首都(LCT)
    BZOJ4530 [BJOI2014]大融合(LCT)
    BZOJ2631: tree(LCT)
    BZOJ2002: [Hnoi2010]Bounce 弹飞绵羊(LCT)
    BZOJ3282: Tree (LCT模板)
    [NOI2008]假面舞会(DFS)
    斜率优化dp练习
    BZOJ2049[Sdoi2008]Cave 洞穴勘测(LCT模板)
  • 原文地址:https://www.cnblogs.com/Walker-lyl/p/5592048.html
Copyright © 2020-2023  润新知