zoukankan      html  css  js  c++  java
  • 8条规则图解JavaScript原型链继承原理

    原形链是JS难点之一,而且很多书都喜欢用一大堆的文字解释给你听什么什么是原型链,就算有图配上讲解,有的图也是点到为止,很难让人不产生疑惑。

    我们先来看一段程序,友情提示sublimeText看更爽:

    <!DOCTYPE html>
    <html>
    <head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
    <title>《JavaScript高级程序设计(第三版)》Page163页的源码</title>
    <link href="" rel="stylesheet">
    </head>
    <body>
        <script type="text/javascript">
        function SuperType(){
            this.property = "我是父亲的属性";
        }
        SuperType.prototype.getSuperValue = function(){
            return this.property;
        }
        function SubType(){
            this.subproperty = "我是孩子的属性";
        }
        SubType.prototype = new SuperType(); 
        SubType.prototype.getSubValue = function(){
            return this.subproperty;
        }
        var instance = new SubType();  
        alert(instance.getSuperValue());//我是父亲的属性
    </script>
    </body>
    </html>

    有的人可能会觉得很熟悉,这是《JavaScript高级程序设计(第三版)》Page163页的源码。ps:将原来的false,true改成中文字符串比较容易看懂

    但是下面的图我看了就觉得很怪了,原来的原型不是换了吗?怎么还指向呢?然后自己画了一个图并且证明了一遍,才发现原来书里画的也是错的。


    然后就引出了想要图解原型链的想法,我们来看下面,友情提示sublimeText看更爽:

    <!DOCTYPE html>
    <html>
    <head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
    <title>JS原形链图解</title>
    </head>
    <body>
        <script type="text/javascript">
        function SuperType(){
            this.property = "我是父亲的属性";
        }
        SuperType.prototype.getSuperValue = function(){
            return this.property;
        }
        function SubType(){
            this.subproperty = "我是孩子的属性";
        }
        var SubPro = SubType.prototype;//因为下面要改变原型,先用一个引用存起来,不然等下找不到
        console.log("没改变原型之前是相等的:"+(SubType.prototype===SubPro))
        SubType.prototype = new SuperType(); //这里改变了SubType的原型使它指向一个SuperType实例
        console.log("给SubType构造函数换了原型之后是不等的:"+(SubType.prototype===SubPro));
        //这里可以看出原型已经改变了
        SubType.prototype.getSubValue = function(){
            return this.subproperty;
        }
        var instance = new SubType();
        //****************************
        //下面开始证明图
        //****************************
        console.log("window对象下面添加了一个函数SuperType:"+(window.hasOwnProperty('SuperType')));
        console.log("window对象下面添加了一个函数SubType:"+(window.hasOwnProperty('SubType')));
        //下面全部为true
        console.log("1:"+(SuperType.prototype===SuperType.prototype));
        console.log("2:"+(SuperType===SuperType.prototype.constructor));
        //不能直接找到new SuperType,我们用5来获取
        console.log("3:"+(SubType.prototype.__proto__===SuperType.prototype));
        console.log("4:"+(SubType.prototype.constructor===SuperType));
        console.log("5:上面3,4已经顺带一起证明了,而且直接看代码就可以看出来了");
        //我们用SubPro暂存了原来的原型
        console.log("6:"+(SubPro.constructor===SubType));
        //还是因为取不到new SuperType,我们用SubType.prototype来获取
        console.log("7:"+(instance.__proto__===SubType.prototype));
        console.log("8:"+(instance.constructor===SuperType));
        //****************************
        //下面开始证明各自的属性位置
        //****************************
        console.log("instance有私有的subproperty属性:"+(instance.hasOwnProperty('subproperty')));
        console.log("new SuperType有私有的property属性:"+(SubType.prototype.hasOwnProperty('property')));
        console.log("SuperType.prototype拥有私有的getSuperValue属性:"+(SuperType.prototype.hasOwnProperty('getSuperValue')));
        console.log("SubType.prototype(换过的原型)拥有私有的getSubValue属性:"+(SubType.prototype.hasOwnProperty('getSubValue')));
        console.log("SubPro(原来的原型)拥有私有的getSubValue属性:"+(SubPro.hasOwnProperty('getSubValue')));//false原来的原型没有getSubValue函数,因为是换了原型再添加的函数,所以函数存在实例里面
        </script>
    </body>
    </html>


     下面梳理一下原型链继承:(点击看大图)

    这里通过一个SuperType实例替换SubType的原来的原型,这里的SuperType实例本身就拥有SuperType构造函数以及SuperType.prototype自带的一些属性,那么当取代SubType.prototype(原来的)之后,自然而然的instance实例的属性找不到的要到SubType的原型里面去找,而原来的原型已经被替换了,那么新原型里面有的属性就成了instance可以找到的属性了。ps:这里文字真心不好表达,反正就是往构造函数和构造函数原型找的意思。

    这里当然也发生了略微有点奇怪的两点:

    1. __proto__属性指向新原型(本来是指向旧的SubType.prototype也就是SubPro的),这里勉强可以理解,换了原型嘛!
    2. constructor指向了SuperType构造函数(没有改变原型的话是指向SubType构造函数的),无法理解,代码是var instance = new SubType();怎么顺便把constructor属性也换了?

    但是问题存在我们依旧可以很好理解JS的原型链继承:通过新的实例继承父构造函数与其原型的属性,然后通过替换子构造函数原型达到继承的目的。


     非常建议看过《JavaScript高级程序设计(第三版)》的童鞋看完上面之后回去把书里面原型链这一节看一下,对比一下。如果有问题请留言。万分感谢!如果觉得我写的有用的话请点个赞,这是对我最大的鼓励!么么哒^_^

     原文地址:请点击这里

     
  • 相关阅读:
    HDU 4348 To the moon(可持久化线段树)
    HDU 5875 Function 大连网络赛 线段树
    HDU 5877 2016大连网络赛 Weak Pair(树状数组,线段树,动态开点,启发式合并,可持久化线段树)
    HDU 5876 大连网络赛 Sparse Graph
    HDU 5701 中位数计数 百度之星初赛
    CodeForces 708B Recover the String
    Java实现 蓝桥杯 算法提高 套正方形(暴力)
    ASP.NET生成验证码
    ASP.NET生成验证码
    ASP.NET生成验证码
  • 原文地址:https://www.cnblogs.com/manfredHu/p/4421921.html
Copyright © 2011-2022 走看看