JS中的原型和原型链详解

JS中的原型和原型链是大家彻底搞懂JS面向对象及JS中继承相关知识模块非常重要的一个模块,一旦突破这块知识点,相信大家对JS会有一个更新、更全面的认识。

一、 什么是原型?

任何对象都有一个原型对象,这个原型对象由对象的内置属性_proto_指向它的构造函数的prototype指向的对象,即任何对象都是由一个构造函数创建的,但是不是每一个对象都有prototype,只有方法才有prototype。

二、 为什么要使用原型

试想如果我们要通过Foo()来创建很多很多个对象,如果我们是这样子写的话。

那么我们创建出来的每一个对象,里面都有showName和showAge方法,这样就会占用很多的资源。

而通过原型来实现的话,只需要在构造函数里面给属性赋值,而把方法写在Foo.prototype属性(这个属性是唯一的)里面。这样每个对象都可以使用prototype属性里面的showName、showAge方法,并且节省了不少的资源。如下图所示:

要想彻底了解原型,我们必须从对象的创建过程开始。就像你要彻底了解一个人,要从他的原生家庭,从他的出生环境了解起。有些基因是从出生就开始植入到对象内的。所以,我们首先来看对象的创建过程。

三、 创建对象的过程

1. 声明方法的过程

首先,当我们声明一个function关键字的方法时,会为这个方法添加一个prototype属性,指向默认的原型对象,并且此prototype的constructor属性也指向方法对象。此二个属性会在创建对象时被对象的属性引用。

2. 通过构造函数创建对象

实践证明,new出来的对象,它的constructor指向了方法对象,它的_proto_和prototype相等。即new一个对象,它的_proto_属性指向了方法的prototype属性,并且constructor指向了prototype的constructor属性。

为什么会导致上述结果?这涉及到对象创建的过程,一旦明白对象创建的过程这个问题就迎刃而解了。下面我们来看

3. 创建一个对象的过程

JS中创建对象的常见方法有三种:①通过字面量创建对象;②通过构造函数创建对象;③通过Object.create方法创建对象。

方式一:通过字面量创建对象

这种形式就是对象字面量,通过对象字面量构造出的对象,其__proto__指向Object.prototype。

所以,其实Object是一个函数也不难理解了。Object、Function都是是JS自带的函数对象。我们可以通过下面的代码验证:

方式二:通过构造函数创建对象

new一个构造函数,相当于实例化一个对象,这期间其实进行了这三个步骤:

【1】创建对象,设为f,即: var  f = {};

【2】上文提到了,每个对象都有__proto__属性,该属性指向一个对象,这里,将f对象的__Proto__指向构造函数Foo的原型对象(Foo.prototype);

【3】将f作为this去调用构造函数Foo,从而设置f的属性和方法并初始化。

当这3步完成,这个f对象就与构造函数Foo再无联系,这个时候即使构造函数Foo再加任何成员,都不再影响已经实例化的f对象了。

此时,f对象具有了name和age属性,同时具有了构造函数Foo的原型对象的所有成员,当然,此时该原型对象是没有成员的。

上述过程可以用下列代码表述:

简单的总结下就是:

【1】js在创建对象的时候,都有一个叫做__proto__的内置属性,用于指向创建它的函数对象的原型对象prototype;

【2】那么一个对象的__proto__属性究竟怎么决定呢?答案显而易见了:是由构造该对象的方法决定的。

方式三:通过Object.create方法创建对象

这种情况下,person2的__proto__指向person1。在没有Object.create函数的时候,人们大多是这样做的:

4. 延伸

从上面说明的过程中,我们发现只要是对象是由构造函数来创建的,并且内部二个属性是从构造函数的prototype衍生的一个指向,而构造函数的prototype也是一个对象,那么它应该肯定也有一个构造函数,首先它是一个Object {} 对象,那么它的构造函数肯定是Object,所以就会有一个指针_proto_指向Object.prototype。最后Object.prototype因为没有_proto_,指向null,这样就构成了一个原型链。

四、 原型链

1.  什么是原型链?

原型链的核心就是依赖对象的_proto_的指向,当自身不存在的属性时,就一层层的扒出创建对象的构造函数,直至到Object时,就没有_proto_指向了。

也就是说,当试图得到一个对象的属性时,如果这个对象本身不存在这个属性,那么就会去它构造函数的’prototype’属性中去寻找。那又因为’prototype’属性是一个对象,所以它也有一个’_ _ proto_ _'属性。

上述代码运行结果,直观地用下图表示,更便于大家理解:

首先,fn的构造函数是Foo()。所以:fn._ _ proto _ _ ===  Foo.prototype

又因为Foo.prototype是一个普通的对象,它的构造函数是Object,所以:

Foo.prototype._ _ proto _ _ ===  Object.prototype

通过上面的代码,我们知道这个toString()方法是在Object.prototype里面的,当调用这个对象的本身并不存在的方法时,它会一层一层地往上去找,一直到null为止。

所以当fn调用toString()时,JS发现fn中没有这个方法,于是它就去Foo.prototype中去找,发现还是没有这个方法,然后就去Object.prototype中去找,找到了,就调用Object.prototype中的toString()方法。

这就是原型链,fn能够调用Object.prototype中的方法正是因为存在原型链的机制。

另外,在使用原型的时候,一般推荐将需要扩展的方法写在构造函数的prototype属性中,避免写在_ _ proto _ _属性里面。(上述为什么使用原型有解释原因)

5.  如何分析原型链?

因为_proto_实质找的是prototype,所以我们只要找这个链条上的构造函数的prototype。其中Object.prototype是没有_proto_属性的,它==null。

属性搜索原则:

【1】当访问一个对象的成员的时候,会现在自身找有没有,如果找到直接使用。

【2】如果没有找到,则去原型链指向的对象的构造函数的prototype中找,找到直接使用,没找到就返回undifined或报错。

始终牢记:JS在创建对象的时候,都有一个叫做__proto__的内置属性,用于指向创建它的函数对象的原型对象prototype。

而原型链的基本思想就是利用原型让一个引用类型继承另一个引用类型的属性和方法。

五、 总结

1、所有的引用类型(数组、函数、对象)可以自由扩展属性(除null以外)。

2、所有的引用类型都有一个’_ _ proto_ _'属性(也叫隐式原型,它是一个普通的对象)。

3、所有的函数都有一个’prototype’属性(这也叫显式原型,它也是一个普通的对象)。

4、所有引用类型,它的’_ _ proto_ _'属性指向它的构造函数的’prototype’属性。

5、当试图得到一个对象的属性时,如果这个对象本身不存在这个属性,那么就会去它的’_ _ proto_ _'属性(也就是它的构造函数的’prototype’属性)中去寻找。

给大家推荐个cocos学习交流群 点击链接即可加群  加群链接

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,456评论 5 477
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,370评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,337评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,583评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,596评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,572评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,936评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,595评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,850评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,601评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,685评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,371评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,951评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,934评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,167评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 43,636评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,411评论 2 342

推荐阅读更多精彩内容