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);

修改一下:

总结

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

posted @ 2020-03-13 16:57  敖毛毛  阅读(764)  评论(0编辑  收藏  举报