js 原型与原型链
族语1996 人气:0
### 前言
什么是原型?
```
原型,汉语词语,读音为yuán xíng。指原来的类型或模型,特指文学艺术作品中塑造人物形象所依据的现实生活中的人。
```
狭义上将是原型人物。通常这样的解释,往往我们会觉得原型与产品之间,是在原型上破坏性的加工。
如果这样理解的话,那么将会对js的原型理解艰难,因为英文翻译过来是抽象的。
js的原型是扩展的意思,就像我们学数据结构的双向链表一样。
![](https://img2020.cnblogs.com/blog/1289794/202003/1289794-20200313100121098-1013013697.png)
也就是说原型是扩展的对象的一个属性。
那么什么是原型链?
![](https://img2020.cnblogs.com/blog/1289794/202003/1289794-20200313100633304-1304378593.png)
原型链指的是指向原型的这条连接,直到指向null为指,因为这个时候链接就断了。
好的概念理解完了,开始正文吧。下面理解,均为个人理解,如有不对望指出。
### 正文
上面写道扩展对象的一个属性指向了原型,那么这个属性是什么?
是__proto__。
#### __proto__ 与 prototype
看一段代码:
```
var obj= new Object();
consoleProto(obj);
function consoleProto(obj){
if(obj!=null)
{
console.log(obj.__proto__);
consoleProto(obj.__proto__);
}
}
```
![](https://img2020.cnblogs.com/blog/1289794/202003/1289794-20200313104108795-1899893756.png)
上文我通过递归的方式,把原型链打印了出来。
也就是说我创建一个对象,都会有一个属性__proto__指向另外一个对象。
![](https://img2020.cnblogs.com/blog/1289794/202003/1289794-20200313104446620-550736328.png)
现在我不关心null,我更关心的是红框中的对象到底是啥?
接来下我写了另一段代码:
```
var obj= new Object();
var obj2=new Object();
console.log(obj.__proto__===obj2.__proto__);
```
返回的结果为:true。
这个说明什么呢?说明任何一个对象的原型最终会基于一个公共原型对象。
也就是说new Object() 会把一个新的对象增加一个公共的对象引用。
那么new Object()是如何获取这个对象的呢?调用了什么函数可以获取到这个对象?或者说Object本身就带有这个公共属性?
我写下了另外一段代码:
```
```
结果为true。
原来Obect本身就带有这个属性。
![](https://img2020.cnblogs.com/blog/1289794/202003/1289794-20200313115142218-314255995.png)
那么再往上推,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。
如图:
![](https://img2020.cnblogs.com/blog/1289794/202003/1289794-20200313123019182-159474159.png)
那么上图中的原型对象是否就是原始对象。有两种方法可以证明一种就是没有原型,一种就是和原始对象做对比。
```
console.log(Object1.__proto__==Object.prototype);
```
我采用第二种,结果不是。同时说明Fuction 不是 Object的构造函数。
实际上是这样的:
```
console.log(Function.prototype==Function.prototype);
console.log(Function.prototype.__proto__==Object.prototype);
```
![](https://img2020.cnblogs.com/blog/1289794/202003/1289794-20200313134310378-1955278712.png)
两者都为true。
上述结论图:
![](https://img2020.cnblogs.com/blog/1289794/202003/1289794-20200313140314537-1433543565.png)
其中内置方法没有prototype,所以不是每个函数都有prototype。
#### 再次__proto__ 与 prototype
上述提及的是内部的对象关系,那么我们书写的时候不用理会这么多了。
```
function Tree(){
}
var newtree=new Tree();
console.log(newtree.__proto__==Tree.prototype);
```
关系为:
![](https://img2020.cnblogs.com/blog/1289794/202003/1289794-20200313141159905-2016486767.png)
#### constructor
既然构造函数能够知道原型,原型是否能够知道构造函数,也是可以的。
```
console.log(Tree==Tree.prototype.constructor);
```
两者相生相伴,一起出生。
![](https://img2020.cnblogs.com/blog/1289794/202003/1289794-20200313141820610-969157449.png)
#### 为什么说原型链可以实现继承?
```
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);
```
![](https://img2020.cnblogs.com/blog/1289794/202003/1289794-20200313165337582-967333128.png)
修改一下:
![](https://img2020.cnblogs.com/blog/1289794/202003/1289794-20200313165520000-1198270181.png)
### 总结
以上皆为个人理解,如有不对,望请指点。
加载全部内容