zoukankan      html  css  js  c++  java
  • 一个样例让你明确原型对象和原型链

    开篇

    之前对js中的原型链和原型对象有所了解,每当别人问我什么是原型链和原型对象时,我总是用非常官方(事实上自己不懂)的解释去描写叙述。有一句话说的好:假设你不能把一个非常复杂的东西用最简单的话语描写叙述出来,那就说明你没有真正的理解。

    近期正在读《Javascript高级程序设计》,书中对原型对象和原型链的描写叙述让我受益匪浅,以下仅用一个对照性的样例来说明。

    我们常常会这么写

        function Person () {
            this.name = 'John';
        }
        var person = new Person();
        Person.prototype.say = function() {
            console.log('Hello,' + this.name);
        };
        person.say();//Hello,John

    上述代码非常easy,Person原型对象定义了公共的say方法,尽管此举在构造实例之后出现,但由于原型方法在调用之前已经声明,因此之后的每一个实例将都拥有该方法。从这个简单的样例里,我们能够得出:

    原型对象的用途是为每一个实例对象存储共享的方法和属性。它不过一个普通对象而已。而且全部的实例是共享同一个原型对象,因此有别于实例方法或属性。原型对象仅有一份。

    所以就会有例如以下等式成立:

        person.say == new Person().say

    可能我们也会这么写

        function Person () {
            this.name = 'John';
        }
        var person = new Person();
        Person.prototype = {
            say: function() {
                console.log('Hello,' + this.name);
            }
        };
        person.say();//person.say is not a function

    非常不幸,person.say方法没有找到,所以报错了。事实上这样写的初衷是好的:由于假设想在原型对象上加入很多其它的属性和方法,我们不得不每次都要写一行Person.prototype,还不如提炼成一个Object来的直接。可是此样例巧就巧在构造实例对象操作是在加入原型方法之前,这样就会造成一个问题:
    var person = new Person()时,Person.prototype为:Person {} (当然了,内部还有constructor属性),即Person.prototype指向一个空的对象{}。

    而对于实例person而言,其内部有一个原型链指针proto,该指针指向了Person.prototype指向的对象,即{}。接下来重置了Person的原型对象,使其指向了另外一个对象,即

     Object {say: function}

    这时person.proto的指向还是没有变。它指向的{}对象里面是没有say方法的,由于此报错。

    从这个现象我们能够得出:

    在js中,对象在调用一个方法时会首先在自身里寻找是否有该方法。若没有。则去原型链上去寻找,依次层层递进,这里的原型链就是实例对象的proto属性

    若想让上述样例成功执行,最简单有效的方法就是交换构造对象和重置原型对象的顺序,即:

        function Person () {
            this.name = 'John';
        }
        Person.prototype = {
            say: function() {
                console.log('Hello,' + this.name);
            }
        };
        var person = new Person();
        person.say();//person.say is not a function

    一张图让你秒懂原型链

    事实上。只须要明确原型对象的结构就可以:

        Function.prototype = {
            constructor : Function,
            __proto__ : parent prototype,
            some prototype properties: ...
        };

    总结:

    函数的原型对象constructor默认指向函数本身。原型对象除了有原型属性外,为了实现继承,另一个原型链指针proto,该指针指向上一层的原型对象,而上一层的原型对象的结构依旧相似,这样利用proto一直指向Object的原型对象上,而Object的原型对象用Object.proto = null表示原型链的最顶端,如此变形成了javascript的原型链继承,同一时候也解释了为什么全部的javascript对象都具有Object的基本方法。

    Blog同步

  • 相关阅读:
    从网络得到图片数据保存到手机中,
    jni 写一个简单的photoshop
    rman catalog配置简要笔记
    如何利用c中的指针实现两个8bit的数合并为16bit
    使用eclipse远程调试weblogic
    迁移11g Rac中OCR和VOTEDISK
    SQL SERVER导入数据到ORACLE的方法总结
    SQL SERVER如何通过SQL语句获服务器硬件和系统信息
    ORACLE SQL Developer日期显示格式设置
    mysqldump:Couldn't execute 'show create table `tablename`': Table tablename' doesn't exist (1146)
  • 原文地址:https://www.cnblogs.com/mengfanrong/p/5275434.html
Copyright © 2011-2022 走看看