理解js中的原型链,prototype与__proto__的关系

一、了解创建函数对象时new的过程。 我们先看一段代码:

    
我们可以把new的过程拆分成以下三步:

    <1> var p={}; 初始化一个对象p。

    <2> p.__proto__=Person.prototype;

    <3> Person.call(p);也就是说构造p,也可以称之为初始化p。

二、 此三步的关键点时是第二步,以下为证明材料证明一下:

   

1、首先,我们先理解下proto是什么?

    每个对象都会在其内部初始化一个属性,就是__proto__,当我们访问一个对象的属性时,如果这个对象内部不存在这个属性,那么他就会去__proto__里找这个属性,这个__proto__又会有自己的__proto__,一直找下去,这也就是我们平时所说的原型链的概念。
2、了解proto属性特点
     按照标准,__proto__是不对外公开的,也就是说是个私有属性,但   是Firefox的引擎将他暴露了出来成为了一个共有的属性,我们可以对外访问和设置。

3、让我们看一下下面这些代码:

   

那就让我们看下为什么p可以访问Person的Say?

首先var p=new Person();可以得出p.proto=Person.prototype。那么当我们调用p.Say()时,首先p中没有Say这个属性,于是,他就需要到他的proto中去找,也就是Person.prototype,而我们在上面定义了 Person.prototype.Say=function(){}; 于是,就找到了这个方法。

4、让我们看个更复杂的原型链例子。

   

我们来做这样的推导:

var p=new Programmer()可以得出p.proto=Programmer.prototype;

而在上面我们指定了Programmer.prototype=new Person();
我们来这样拆分,var p1=new Person();Programmer.prototype=p1;
那么:
p1.proto=Person.prototype;
Programmer.prototype.proto=Person.prototype;
根据上面得到p.proto=Programmer.prototype。
可以得到p.proto.proto=Person.prototype。

输出结果分析:

p.Say()。由于p没有Say这个属性,于是去p.proto也就是Programmer.prototype,也就是p1中去找由于p1中也没有Say,那就去p.proto.proto,也就是
Person.prototype中去找,于是就找到了alert(“Person say”)的方法。

其它同理。

三、一幅图说明它们之间的关系

Javascript中12个内置对象,其中10个函数类型,2个对象类型。


Paste_Image.png

上图有十种构造器函数,分别为:date Array Number Object Bloolean String Event Error RegExp Function,这些构造器函数都可以通过new来实例化一个对象

注意:

1、所有构造器的prototype都是对象(object)类型,只有Function.prototype是函数(function)类型,这是为了保证函数构造器们的__proto__指向的都是函数。
2、JSON和Math不是构造器函数,他们是普通的对象。只有构造器函数才能使用new 关键字实例化一个对象,而JSON和Math已经是对象了,所以我们可以不用实例化直接使用JSON和Math中的属性和方法。

你可能感兴趣的:(理解js中的原型链,prototype与__proto__的关系)