zoukankan      html  css  js  c++  java
  • js 原型与原型链

    前言

    什么是原型?

    原型,汉语词语,读音为yuán xíng。指原来的类型或模型,特指文学艺术作品中塑造人物形象所依据的现实生活中的人。
    

    狭义上将是原型人物。通常这样的解释,往往我们会觉得原型与产品之间,是在原型上破坏性的加工。

    如果这样理解的话,那么将会对js的原型理解艰难,因为英文翻译过来是抽象的。

    js的原型是扩展的意思,就像我们学数据结构的双向链表一样。

    也就是说原型是扩展的对象的一个属性。

    那么什么是原型链?

    原型链指的是指向原型的这条连接,直到指向null为指,因为这个时候链接就断了。

    好的概念理解完了,开始正文吧。下面理解,均为个人理解,如有不对望指出。

    正文

    上面写道扩展对象的一个属性指向了原型,那么这个属性是什么?

    是__proto__。

    proto 与 prototype

    看一段代码:

    var obj= new Object();
    consoleProto(obj);
    function consoleProto(obj){
    	  if(obj!=null)
    	  {
    		console.log(obj.__proto__);
    		consoleProto(obj.__proto__);
    	  }
    }
    

    上文我通过递归的方式,把原型链打印了出来。

    也就是说我创建一个对象,都会有一个属性__proto__指向另外一个对象。

    现在我不关心null,我更关心的是红框中的对象到底是啥?

    接来下我写了另一段代码:

    var obj= new Object();
    var obj2=new Object();
    console.log(obj.__proto__===obj2.__proto__);
    

    返回的结果为:true。

    这个说明什么呢?说明任何一个对象的原型最终会基于一个公共原型对象。

    也就是说new Object() 会把一个新的对象增加一个公共的对象引用。

    那么new Object()是如何获取这个对象的呢?调用了什么函数可以获取到这个对象?或者说Object本身就带有这个公共属性?

    我写下了另外一段代码:

    <script>
    var obj= new Object();
    console.log(Object.prototype===obj.__proto__);
    </script>
    

    结果为true。

    原来Obect本身就带有这个属性。

    那么再往上推,Object是什么,Object是一个函数。

    把Object 打印出来,然后提出疑问是否每个函数都具有prototype 属性?

    function Object1(){
    }
    console.log(prototype);
    
    console.log(Object1.prototype==Object.prototype);
    

    打印出来是prototype 有值,后面的结果为false。

    证明了每个函数,都具有prototype,但是Object比较特殊,其Object内置函数。

    他们的关系如下:

    console.log(Object1.prototype.__proto__==Object.prototype);
    

    那么现在单独讨论Object1,Object1是一个函数但是同时也是一个对象,那么从对象的角度来看下,对象想到的是__proto__.

    function Object1(){
    
    }
    console.log(Object1.__proto__==Function.prototype);
    

    得出的结果为true。

    如图:

    那么上图中的原型对象是否就是原始对象。有两种方法可以证明一种就是没有原型,一种就是和原始对象做对比。

    console.log(Object1.__proto__==Object.prototype);
    
    

    我采用第二种,结果不是。同时说明Fuction 不是 Object的构造函数。

    实际上是这样的:

    console.log(Function.prototype==Function.prototype);
    console.log(Function.prototype.__proto__==Object.prototype);
    

    两者都为true。

    上述结论图:

    其中内置方法没有prototype,所以不是每个函数都有prototype。

    再次__proto__ 与 prototype

    上述提及的是内部的对象关系,那么我们书写的时候不用理会这么多了。

    function Tree(){
    }
    
    var newtree=new Tree();
    
    console.log(newtree.__proto__==Tree.prototype);
    

    关系为:

    constructor

    既然构造函数能够知道原型,原型是否能够知道构造函数,也是可以的。

    console.log(Tree==Tree.prototype.constructor);
    

    两者相生相伴,一起出生。

    为什么说原型链可以实现继承?

    function Tree(){
    
    }
    
    Tree.prototype.name="白杨树";
    
    var newtree=new Tree();
    
    console.log(newtree.name);
    

    这时候打印出来的是“白杨树“。也就是说如果newtree找不到,则会去根据原型链找原型,一直找下去,知道找到为止。

    同样:

    console.log(newtree.contructor==Person);
    

    也就是因为newtree没有这个属性,只好找原型了。

    最后一笔

    console.log(Tree.prototype.__proto__.constructor);
    

    修改一下:

    总结

    以上皆为个人理解,如有不对,望请指点。

  • 相关阅读:
    从亚马逊、微软、谷歌的云之争,看国内云计算的未来
    即使是菜鸟,也能配置出一个网站
    为什么软件开发周期通常是预期的两三倍?
    2015-2016前端知识体系
    UOJ269【清华集训2016】如何优雅地求和【数论,多项式】
    LOJ166 拉格朗日插值 2【卷积,NTT】
    CF1140F Extending Set of Points 【按时间分治,并查集】
    CF1168C And Reachability 【构造,dp】
    CF1182F Maximum Sine【类欧,扩欧】
    牛客 可见山峰对数量(进阶)
  • 原文地址:https://www.cnblogs.com/aoximin/p/12449080.html
Copyright © 2011-2022 走看看