• Javascript之旅——第十一站:原型也不好理解?


     

    写到这篇,我的js系列也快接近尾声了,所以这个系列不会遗留js来实现面向对象的核心——原型,有些人说原型不好理解,其实嘛,要想系统的理解原型,最便捷的方式就是看看经典的书,少看些博客,博客这东西只是博主自己的个人理解,充其量是些配味的佐料。

    一:继承

    如果你熟悉C#的话,你肯定会知道,所有的类都是继承于Object的,这样我就拥有Object所具有的功能了,如下图中我定义的Person类。

    从图中可以看到,在C#中到处都是继承,下一步我要做的就是自定义继承,如下图中我定义的Student类,让它继承Person.Name属性。

    这些对于玩C#的人来说都是很司通见惯的,那么下一个问题来了,这些真正的面向对象的东西,在js中该怎么玩呢?当然就要用到大名鼎鼎的prototype属性了。

    二:用JS来模仿C#的继承

    1.默认继承Object

    我们都知道在js中的所有引用类型也同样继承于Object,这样也就具有Object的功能了,但是你有没有考虑过,比如下图中的Person到底是怎么继承了Object的所有属性和方法呢?

    看到上图后,你是不是很好奇呢?其实原理真的很简单,用chorme的watch expressions一看你就一清二楚了。

    第一眼看到不知道你会不会眼晕?听我慢慢解释,从上面的图中不难看到,其实有这么个原型链的关系:

    p.__proto__ =Person.prototype

    Person.prototype.__proto__ -> new Object()

    不知道你看懂了没?其实这里最重要的就是__proto__属性,首先你要知道,每个实例都具有这么个__proto__属性,因为这是核心,比如你要找p.toString()方法, js引擎会优先在Person function中找toString()方法,发现没有。。。花擦。。。没辙只能通过p.__proto__属性继续往上查找,到了Person.prototype,从图中可以看到prototype是一个具有constructor属性的对象,因为只有一个属性,所以也没找到tostirng()方法,然后沿着Person.prototype._proto__找到了Object,在这里我们就找到了toString()方法。

    2.自定义继承

    我们知道prototype是个非常重要的属性,为了模仿C#中Student类继承于Person类,这次我需要做的是让Studnet.prototype=new Person()就好了。

    从图中可以看到student实例已经含有Name属性了,我们现在已经知道有一个原型链查找的过程,比如我现在通过student.__proto__找到了new Person(),然后也看到了new Person()具有Name属性,我想你现在也知道,在Person函数中也有一个__proto__属性,它是指向Object的,如果说我在new Person()中没有找到,那么会继续通过Person.__proto__(Student.prototype.proto__)继续往上找,一直找到顶端为止。

    三:详解prototype

    1. prototype到底是什么?

    从上一章中我想你对prototype应该有了宏观了解,可以看到其实prototype只不过是一个包含constructor属性的Object对象,其中constructor属性是指向当前function的一个指针,代码还原如下:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    <script type="text/javascript">
            function Person() {
                this.Name = "ctrip";
            }
     
            Person.prototype = {
                constructor: Person  //指向Person的constructor
            };
     
            var p = new Person();
        </script>

    2. prototype上面的属性可以被所有实例共享。

    这个之所以能够共享,是因为每个实例都有__proto__属性,包括function的prototype属性也是有__proto__属性的,这是因为prototype本质上也是一个对象的实例,所以js在查找某个属性是否存在的时候会通过__proto__属性一直追踪到object。

    3. 如果function中的属性与prototype属性冲突了怎么办?

    看到答案后,我想你也非常清楚了,毕竟你已经理解了原型链的查找,因为js引擎查找过程是先从本函数查找,如果找到就return,找不到继续通过__proto__往上找,很好理解的。


    原文出处: 一线码农的博客   欢迎分享原创到伯乐头条

  • 相关阅读:
    NanoProfiler
    NanoProfiler
    Open Source Cassandra Gitbook for Developer
    Android Fragment使用(四) Toolbar使用及Fragment中的Toolbar处理
    Android Fragment使用(三) Activity, Fragment, WebView的状态保存和恢复
    Android Fragment使用(二) 嵌套Fragments (Nested Fragments) 的使用及常见错误
    Android Fragment使用(一) 基础篇 温故知新
    Set up Github Pages with Hexo, migrating from Jekyll
    EventBus源码解析 源码阅读记录
    Android M Permission 运行时权限 学习笔记
  • 原文地址:https://www.cnblogs.com/sunscheung/p/4342162.html
Copyright © 2020-2023  润新知