zoukankan      html  css  js  c++  java
  • JavaScript---继承

      JavaScript---继承

          JavaScript语言的继承机制---由于JavaScript没有‘类(class)’和‘实例(instance)’的概念,他是靠‘原型链(prototype  chain)’模式来实现继承的

      要理解JavaScript的继承机制,首先,要清楚这几个概念:构造函数,实例对象,prototype,constructor、__proto__  以及他们之间的关系。

          构造函数:用来初始化新创建的对象的函数是构造函数。(你可以把构造函数看成是“类”)

          实例对象:通过构造函数的new操作创建的对象是实例对象。可以用同一个构造函数,构造多个实例对象。

          prototype:每个函数(当然包括构造函数)都有一个prototype属性,它是一个对象。我们称它为‘原型对象’  prototype:{...}

          constructor:每个对象都有一个constructor属性,它是一个函数:constructor:fn(){...} 它的作用就是指向该原型对象对应的构造函数。由于实例对象可以继承原型对象的属性,所以实例对象也拥有constructor属性,同样指向原型对象对应的构造函数

          __proto__:每个实例对象都有一个proto属性,指向创建该实例对象的构造函数的原型对象(可以理解为 实例对象---》构造函数的原型对象)

      熟练使用JavaScript的继承必须要对这几个概念烂熟于心。

        接下来结合图示来分析一下。

      

        要想清楚的了解JavaScript的继承机制,这些概念是必须烂熟于心的。

        

        JavaScript的继承 ---指的是子类继承父类的属性和方法

        JavaScript的继承特点:1.子类拥有父类所有的属性和方法(代码复用);2.子类可以扩展自己的属性和方法(更加灵活);3.子类可以重写父类的方法

        JavaScript的继承方式

          1.组合继承

            

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>组合继承法</title>
        <script>
            function Person(name,age,gender,geyan){
                this.name = name;
                this.age = age;
                this.gender = gender;
                this.geyan = geyan;
            }
    
            Person.prototype.say = function(){
                console.log(`我叫${this.name},${this.gender},我今年${this.age}岁,我的人生格言是:${this.geyan}`);
            }
    
    
            var p1 = new Person('lx',18,'','我姓谢,王菲的哪个谢');
            var p2 = new Person('lw',45,'','你有困难我帮忙,我住隔壁,我姓王');
            p1.say();
            p2.say();
    
    
            function Student(){
                // 借用构造函数法
                // Person.call(this,name,age,gender,geyan)
                Person.apply(this,arguments);
            }
    
    
            //原型链继承法
            Student.prototype = new Person();
            var s1 = new Student('小明', 12, '', '姐姐,约吗');
            s1.say();
            console.log(s1);
        </script>
    </head>
    <body>
        
    </body>
    </html>

      chrome显示如下:

      组合继承主要使用:1.借用构造函数法--使用call方法或apply方法借用父类的属性,使子类可以使用。 2.原型链继承法---将父类的实例对象赋给子类的原型对象,这样,子类的原型对象就继承到了父类的原型对象里的方法(子类原型对象---》父类原型对象)

      组合继承的弊端:1.多次执行了父类构造函数  在我们的例子中, 每创建一个子类的实例sn,都要调用一次父类构造函数 ,很麻烦。  2.在原型对象里生成多余的属性  原因在于原型链继承这一步中,父类的实例对象的属性也被子类的原型对象继承了。

      知道他的弊端之后,就能加以改进了:将原型链继承法用新的方法替代,这个新的方法叫做:原生式继承法。这个方法不会生成多余的属性

        来看改进过的代码:

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>组合继承法</title>
        <script>
            function Person(name,age,gender,geyan){
                this.name = name;
                this.age = age;
                this.gender = gender;
                this.geyan = geyan;
            }
    
            Person.prototype.say = function(){
                console.log(`我叫${this.name},${this.gender},我今年${this.age}岁,我的人生格言是:${this.geyan}`);
            }
    
    
            var p1 = new Person('lx',18,'','我姓谢,王菲的哪个谢');
            var p2 = new Person('lw',45,'','你有困难我帮忙,我住隔壁,我姓王');
            p1.say();
            p2.say();
    
    
            function Student(){
                // 借用构造函数法
                // Person.call(this,name,age,gender,geyan)
                Person.apply(this,arguments);
            }
    
    
            //原生式继承法
            function object(o){
                function F(){}
                F.prototype = o;
                return new F();
            }
            Student.prototype = object(Person.prototype);
            var s1 = new Student('小明',12, '', '姐姐,约么?');
            s1.say();
            console.log(s1);
        </script>
    </head>
    <body>
        
    </body>
    </html>

      在chrome中显示:

       原生式继承法的精髓在于:直接继承父类的原型,而不是向原型链继承那样继承整个父类。但这样又带来了一个新的问题:每次继承都要写一长串的代码。

    怎么偷懒? 好在ES5给我们拓展了关于原型的继承方法----子类.prototype = Object.create(父类.prototype);

       再看一下改进的代码:

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>组合继承法</title>
        <script>
            function Person(name,age,gender,geyan){
                this.name = name;
                this.age = age;
                this.gender = gender;
                this.geyan = geyan;
            }
    
            Person.prototype.say = function(){
                console.log(`我叫${this.name},${this.gender},我今年${this.age}岁,我的人生格言是:${this.geyan}`);
            }
    
    
            var p1 = new Person('lx',18,'','我姓谢,王菲的哪个谢');
            var p2 = new Person('lw',45,'','你有困难我帮忙,我住隔壁,我姓王');
            p1.say();
            p2.say();
    
    
            function Student(){
                // 借用构造函数法
                // Person.call(this,name,age,gender,geyan)
                Person.apply(this,arguments);
            }
    
    
            //ES5的原型使继承法
            Student.prototype = Object.create(Person.prototype);
    
            var s1 = new Student('小明',12,'','姐姐,约么?');
            s1.say();
            console.log(s1);
        </script>
    </head>
    <body>
        
    </body>
    </html>

      

      在chrome中显示:

    这种原型式继承法+借用构造函数法的强力组合就是JavaScript继承方式的第2种方法 叫做寄生继承。这也是最终推荐的继承方式。

    你以为结束了吗??

        讲完了ES5,怎能不讲讲ES6?  ES6给我们准备了一个“大礼包”!!

          开头说到,JavaScript没有“类”的概念。现在有了(JavaScript一直在成长啊)!!ES6中用关键字 class 来定义一个类

      先上代码:

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>ES6中的继承方式</title>
        <script>
    
            // 类: 使用class定义了一个类 Person
            class Person{
    
                // 构造函数  所有的属性都放在constructor函数里(模仿java)
                constructor(name,age){
                    this.name = name;
                    this.age = age;
                }
    
                // 所有的方法写在函数constructor外 注意:并不需要声明方法 直接 say(){...}的形式 相当于 Person.prototype.say = function(){...}
                say(){
                    console.log('say,say');
                }
    
    
                // 静态方法 只会被子类继承, 不会被子类的实例继承
                static sing(){
                    console.log(`我叫${this.name},我会唱歌`);
                }
            }
    
            
    
            // Person.prototype.say = function(){}
    
            var p1 = new Person('lx',18);
            p1.say();
    
    
            // 静态方法的调用
            Person.sing();
    
        //使用extends去继承父类   class 子类 extends 父类{...}
            class Student extends Person{
                constructor(name,age){
                    super(name,age);
                }
            }
    
            var s1 = new Student('小红',12);
    
            Student.sing();
    
            s1.say()
    
    
            console.log(p1,s1)
        </script>
    </head>
    <body>
        
    </body>
    </html>

      在chrome中显示:

    是不是很强大!!!                           考虑到部分浏览器还未兼容ES6的标准。所以还是推荐使用ES5的寄生继承。

    JavaScript的继承机制就暂告一段落了。有问题以后补充                  ----2017-03-21-20:10

  • 相关阅读:
    JAVA共通関数文字列の長さを求める
    JAVA共通関数文字コード変換
    JAVA共通関数文字列に空白を追加する
    JAVA共通関数 半角英数字チェック
    JAVA共通関数項目が半角09か判断する
    JAVA共通関数 指定日の曜日を算出する
    linux添加静态路由(rhel5.4)
    ubuntu编译opencapwap报错解决
    Wireshark网络抓包(二)——过滤器
    net.ipv4.tcp_tw_recycle、net.ipv4.tcp_tw_reuse回收tcp连接总结
  • 原文地址:https://www.cnblogs.com/first-time/p/6594665.html
Copyright © 2011-2022 走看看