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

来源:互联网 发布:数据库时间怎么修改 编辑:程序博客网 时间:2024/05/19 13:27

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


说到prototype,就不得不先说下new的过程。

我们先看看这样一段代码:

1<script type="text/javascript">
2var Person = function () { };
3var p = new Person();
4</script>

很简单的一段代码,我们来看看这个new究竟做了什么?我们可以把new的过程拆分成以下三步:

<1> var p={}; 也就是说,初始化一个对象p。

<2> p.__proto__=Person.prototype;

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

关键在于第二步,我们来证明一下:

1<script type="text/javascript">
2var Person = function () { };
3var p = new Person();
4alert(p.__proto__ === Person.prototype);
5</script>

这段代码会返回true。说明我们步骤2的正确。

那么__proto__是什么?我们在这里简单地说下。每个对象都会在其内部初始化一个属性,就是__proto__,当我们访问一个对象的属性 时,如果这个对象内部不存在这个属性,那么他就会去__proto__里找这个属性,这个__proto__又会有自己的__proto__,于是就这样 一直找下去,也就是我们平时所说的原型链的概念。

按照标准,__proto__是不对外公开的,也就是说是个私有属性,但是Firefox的引擎将他暴露了出来成为了一个共有的属性,我们可以对外访问和设置。

好,概念说清了,让我们看一下下面这些代码:

1<script type="text/javascript">
2var Person = function () { };
3Person.prototype.Say = function () {
4alert("Person say");
5}
6var p = new Person();
7p.Say();
8</script>

这段代码很简单,相信每个人都这样写过,那就让我们看下为什么p可以访问Person的Say。

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

好,接下来,让我们看个更复杂的。

01<script type="text/javascript">
02var Person = function () { };
03Person.prototype.Say = function () {
04alert("Person say");
05}
06Person.prototype.Salary = 50000;
07var Programmer = function () { };
08Programmer.prototype = new Person();
09Programmer.prototype.WriteCode = function () {
10alert("programmer writes code");
11};
12Programmer.prototype.Salary = 500;
13var p = new Programmer();
14p.Say();
15p.WriteCode();
16alert(p.Salary);
17</script>

我们来做这样的推导:

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”)的方法。

其余的也都是同样的道理。

这也就是原型链的实现原理。

最后,其实prototype只是一个假象,他在实现原型链中只是起到了一个辅助作用,换句话说,他只是在new的时候有着一定的价值,而原型链的本质,其实在于__proto__!

原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 手机拨号键没了怎么办 华为手机桌面拨号图标不见了怎么办 华为手机拨号图标不见了怎么办 小米4s屏幕显示黑屏怎么办 平板拨号键没了怎么办 华为手机拨号图标没了怎么办 华为荣耀手机进水了怎么办 华为畅享7黑屏怎么办 华为畅玩7x黑屏怎么办 华为手机打电话时黑屏怎么办 三星a8手机黑屏打不开怎么办 华为手机恢复出厂后黑屏怎么办 华为荣耀4c白屏怎么办 华为荣耀6手机信号不好怎么办 华为荣耀8手机音量小怎么办 无法激活触控id怎么办 魅蓝2卡顿怎么办 小米max2玩王者荣耀卡怎么办 小米4玩王者荣耀卡怎么办 华为荣耀7i卡顿怎么办 华为荣耀7卡的怎么办 荣耀8手机有孤独怎么办 红米note4玩游戏卡怎么办 红米note4x玩游戏卡怎么办 华为4c死屏怎么办 华为4c充电很慢怎么办? 华为4c突然死机了怎么办 华为畅玩4c内存不足怎么办 荣耀4c一直亮屏怎么办 华为手机返回键失灵怎么办 荣耀6p死机了怎么办 荣耀6主板烧坏了怎么办 虚拟运营商倒闭了号怎么办 买到二次放号怎么办 新运动鞋鞋穿着有点紧怎么办 一件代发被买家退货后怎么办? 洗了翻毛的鞋子怎么办 猫眼竹芋泡根了怎么办 双线花叶子卷了怎么办 华为云收藏满了怎么办 小米6云空间满了怎么办