本文由用途意义,进行脑测解析,从需求角度走一遍原型链的发展。
java
js中没有类(没有类,没有类,重要的事情说3遍)只有对象,怎么才能作到继承的效果?c++
var a={x:1} var b={}; b.__proto__=a;
接下来进行约定,当访问b.x
但不存在时,就自动去访问b.__proto__.x
。函数
逻辑上就这么一回事。不过须要注意,这里说的只是访问。b.x=2
这种是没法对a,也就是b.__proto__
形成影响的;同时这个为b赋予了x属性,b.x
将覆盖掉b.__proto__.x
。this
通俗点总结,就是给对象挂一个父对象,当对象没有相应属性时,就去它父对象那里找。
prototype
var A=function(){ } var b = new A();
这个时候又该怎样用__proto__实现继承效果?code
首先函数也是一个对象,除了A();
这样以函数调用,还能A.x=1;
这样把A当普通对象使用(下文中函数、函数对象,都是一回事)。知道这个后实现继承很简单,增长一个属性便可:对象
A.prototype={constructor: A};//提醒一下怕忘记了,这里至关于A增长了属性prototype A.prototype.x=1; b.__proto__ = A.prototype;
js会为每一个这样new出来的对象作这个处理,本身不用写。继承
显然,这里的A.prototype
就相似与一开始例子中的a
,往A.prototype增长属性,那么全部new A()
出来的对象都能访问到这个新的属性。递归
为何js要默认增长constructor: A
这个属性到prototype中?这里与new操做符有关,是为了解决另外一个问题。另外常说的prototype的构造函数,就是指这个。原型链
总结:
反正就是经过new 函数()
这样出来的对象,其__proto__默认指向构造函数(这里说的是函数对象自己,它跟在new后面也被称做构造函数)的prototype属性。
实际上我以为通常不以这个方法进行有大量属性的继承,一是查找有无属性的效率问题,二是new时构造方法把this改成新建对象的指向就足以完成属性的添加和赋值,无需操做prototype进行继承。
__proto__、prototype是什么一回事相信已经了解,剩下的就是常常把人绕晕的Object.prototype、Function.prototype这些东西了。
先提一下,Object
、Function
都是一个函数对象,跟上面的A
差很少,既能new Object()
也能Object.xxx
这样用。
1.因此var b=new Object();
后,b.__proto__===Object.prototype
这个应该没有什么疑问。
2.新的标准中可用b=Object.creat(a)
,可看成是b=new Object(); b.__proto__=a
,仍是这套操做,问题不大。
3.若是是var b={}
这种直接经过字面量建立对象,js会自动进行b.__proto__=Object.prototype
,知道后问题也不大。
4.就是默认状况下,你不手动搞__proto__、prototype的指向,最终__proto__都会去指向Object.prototype。
5.Object.prototype
本质上跟前面示例中的prototype没什么不一样,只是这个prototype会被js自动增长一些属性
6.Object.prototype.__proto__===null
跟在c++/java中遍历链表同样,当__proto__为null时说明到头了。看成js自动设置上去的就行,没什么其余特殊
7.Object.__proto__===Function.prototype
下面再讲。
1.全部的函数对象都是Function的实例。
不是说没有类吗,这个实例又是什么意思?
emmm,习惯说法而已,具体什么操做没研究也不懂,或许看成js自动这样作:
var f=function(){} f.__proto__=Function.prototype; //或者这样理解 var f=new Function(); 而后把你的代码放进去f
2.Function.__proto__===Function.prototype;
前面提过Object、Function都是一个函数对象,把它们代入第1点例子的f
就行。上面第6点同理。
按照理解,可能会这样的疑问:Function.__proto__指向构造函数(再次提醒,是一个对象)的prototype,因此Function这个对象的构造函数是它本身?本身建立本身么?
额。。。我以为这种操做可能就是为了统一,只要记住“全部函数对象的__proto__都是Function.prototype”就行。
3.Function.prototype.__proto__===Object.prototype;
没什么特别的,把Function.prototype
代入上面Object第1点的b
就行,不要特殊看待,硬要说与b
不一样的话,只是由于“函数对象的prototype默认会被增长一个constructor属性”而已,没什么大问题
1.咱们在js中说的“类型”,能够说只是习惯用语,实际上仍旧是没有所谓的类概念的,只有用对象来“模拟类”。
2.prototype就是指向一个普通对象prototype=new Object()
,只不过这个对象被添加其余一些属性后,再被自动放到到函数对象的属性中。
3.__proto__就是 原型/原型对象,不断的找原型的原型最终到--->Object.prototype--->Object.prototype.__proto__ (null)。原型对象多是一个普通的对象;也多是js自动放入到函数对象的prototype
4.我以为js这套东西根本目的是批量为对象赋予属性同时减小代码冗余,上面解析的Object
、Function
、例子中的A
都只是函数对象,不是像java同样的类,平时说对象的类型只是方便平常交流,instanceof也只是很粗暴的递归比较对象__proto__ === 函数对象.prototype
这种。把类的概念丢掉,保留对象、属性这概念,从这出发又回头去实现“类”、“继承”这东西,就出来这么套东西。