zoukankan      html  css  js  c++  java
  • 15条规则解析JavaScript对象布局(__proto__、prototype、constructor)

    大家都说JavaScript的属性多,记不过来,各种结构复杂不易了解。确实JS是一门入门快提高难的语言,但是也有其他办法可以辅助记忆。下面就来讨论一下JS的一大难点-对象布局,究竟设计JS这门语言的人当时是怎么做的?设计完之后又变成了什么?

    我们来看一张图:

     相信大家对这张图都不陌生了,构造函数有一个prototype属性指向其原型。相反原型也有一个constructor指向构造函数。与此同时实例也有一个constructor指向构造函数,这简直就是互相捆绑生怕找不到啊不是吗?

    还有一个我们称之为秘密链接的__proto__属性,原谅我第一眼见到这个属性就觉得特别的怪,_下划线都用上了,驼峰命名规则呢?好吧,这是部分浏览器暴露出来的一个指针而已,可能当时设计的时候随便写出来,突然发现这货有点用就留下了(纯属个人猜测)。

    附上上图的检测代码不信的童鞋可以自己玩玩:

    <!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 Foo(){} //构造函数
        var a = new Foo(); //实例
        console.log(Foo===Foo.prototype.constructor); //true
        console.log(a.constructor===Foo); //true
        console.log(Foo.prototype===Foo.prototype); //true
        console.log(a.__proto__===Foo.prototype); //true
    </script>
    </body>
    </html>

    上面只是基础而已,下面才是真正的重点,为了修改这张图我可是煞费苦心,绞尽脑汁,不知道死了多少脑细胞。

    可能大家已经看晕了,没事冲杯咖啡慢慢看。下面是相应的证明代码,友情提示sublimeText看更爽:

    <!DOCTYPE html>
    <html>
    <head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
    <title>JavaScript对象布局</title>
    </head>
    <body>
        <script type="text/javascript">
            //以下代码全部为true
            console.log("1:"+(Object.prototype.__proto__ === null));
            console.log("2:"+(Function.prototype.__proto__===Object.prototype));
            console.log("3.1:"+(Number.__proto__ === Function.prototype));
            console.log("3.2:"+(Boolean.__proto__ === Function.prototype));
            console.log("3.3:"+(String.__proto__ === Function.prototype));
            console.log("3.4:"+(Object.__proto__ === Function.prototype));
            console.log("3.5:"+(Function.__proto__ === Function.prototype));
            console.log("3.6:"+(Date.__proto__ === Function.prototype));
            console.log("3.7:"+(Error.__proto__ === Function.prototype));
            console.log("3.8:"+(Array.__proto__ === Function.prototype));
            console.log("3.9:"+(RegExp.__proto__ === Function.prototype));
            console.log("4.1:"+(Math.__proto__===Object.prototype));
            console.log("4.2"+(JSON.__proto__===Object.prototype));
            function Foo(){} //构造函数
            var f1 = new Foo(); //实例
            console.log("5:"+(Foo===Foo.prototype.constructor)); 
            console.log("6.1:"+(f1.__proto__===Foo.prototype));
            console.log("7:"+(f1.constructor===Foo)); 
            console.log("8.1:"+(Number.prototype.__proto__===Object.prototype));
            console.log("8.2:"+(Boolean.prototype.__proto__===Object.prototype));
            console.log("8.3:"+(String.prototype.__proto__===Object.prototype));
            console.log("8.5:"+(Function.prototype.__proto__===Object.prototype));
            console.log("8.6:"+(Date.prototype.__proto__===Object.prototype));
            console.log("8.7:"+(Error.prototype.__proto__===Object.prototype));
            console.log("8.8:"+(Array.prototype.__proto__===Object.prototype));
            console.log("8.9:"+(RegExp.prototype.__proto__===Object.prototype));
            console.log("9:"+(Foo.__proto__===Function.prototype));
            var manfred = new Object();//实例对象
            console.log("10:"+(manfred.__proto__===Object.prototype));
            console.log("11:"+(Foo.prototype.__proto__===Object.prototype));
            //manfred为object构造函数产生,manfred.constructor指向function Object()构造函数
            console.log("12:"+(manfred.constructor.__proto__===Function.prototype));
            console.log("13:"+(manfred.constructor===Object.prototype.constructor));
            var hu = new Function();
            console.log("14:"+(hu.constructor.__proto__===Function.prototype));
            console.log("15:"+(hu.constructor===Function.prototype.constructor));
        </script>
    </body>
    </html>

    相信看完这些代码和原图比较之后大家对JS对象之间的关系已经了如指掌了,确实一开始我也让这货搞得头晕晕的,但是画出这张图之后已经觉得没什么了。大家可以自己动手画一下。

    原文地址:请点击这里

    总结(补充):

    1. 普通函数的原型是由Object()构造器构造的,同Object.prototype一样是Object()构造器的一个实例
    2. 普通函数是Function()构造器构造的,同Function.prototype一样是Function()构造器的一个实例
    3. 内部原型链_proto_属性是为了实现继承而存在的,这样,我们可以处于任何目的来修改constructor属性,而不用担心实例与父类的一致性。
  • 相关阅读:
    如何调试 VB 6 的安装源程序 Setup1.VBP?
    Linq和泛型,IEnumerable和IQueryable之间的区别,Lambda表达式,Linq to Sql停止开发转为 Entity Framework
    SQL Server中行列转换 Pivot UnPivot
    一个题目涉及到的50个Sql语句
    Entity Framework中IQueryable, IEnumerable, IList的差别
    [转]git使用指南系列
    一条SQL语句查询出成绩名次 排名 (转)
    MS SQL Server:排名函数详解
    MSSQL中删除所有外键约束的方法
    Model View Presenter Part I – Building it from Scratch
  • 原文地址:https://www.cnblogs.com/manfredHu/p/4418594.html
Copyright © 2011-2022 走看看