js 原型链

什么是原型链?

我们先看一下下面的这个小例子:

let data = {
    name:'merit'
}
alert(data)

这时候,弹出的窗口里面显示着 [object Object],相信大家应该也都见过这个,可是为什么会是这个呢?

其实,再用alert显示对象的时候,会默认调用对象的toString函数,可是,我们明明没有给data设置这个函数啊,那这个函数又是哪里来的呢,这时候我们就把整个data给打印一下看一看:

我们看到,data不止有我们设置的name属性,还有一个我们没设置的__proto__属性,那这属性里面又是些什么东西呢,让我们再打开看一下:

1593426483110.png

这时候我们就在里卖弄看到了我们用到的toString函数。

上面这个是直接创建了一个Object实例对象,下面让我们用构造函数创建一个对象,看看是什么效果:

function MyObj(name){
    this.name = name
}
MyObj.prototype.myToString = function(){
    console.log(this.name)
}
let bar = new MyObj('merit')
alert(bar)

结果显然是和上面的一样为 [object Object],我们来看一看这个的toString方法是怎么得到的:


我们可以看到,bar这个对象本身有一个__proto__属性,这个属性里面竟然还有我们通过MyObj.prototype.myToString定义的函数,这个我们一会儿再说。然后在这个__proto__属性中,还有一个__proto__属性,里面有着我们所需要的toString函数。

当我们调用对象的某个属性的时候,就会先去看它本身有没有这个属性,没有的话,就会去看他的__proto__中有没有这个属性,有的话就调用,没有的话就继续看这个__proto__中的__proto__里面有没有,只到最后一层,如果都没有的话,才会报错。

上面这个例子中,如果把myToString函数名换成toString,那么alert(bar)再调用bar.toString就是我们自己写的内容了。

这种通过__proto__属性一层层的连接形成了一个链的样子就叫做原型链。

prototype与_proto_的关系

当我们创建一个对象的实例的时候,实例本身就会自带一个__proto__属性,该属性指向其构造函数的prototype属性,而所有构造函数的prototype属性都是一个Object的一个实例。而这个实例就会有一个指向Object.prototype的_proto__,所有对象类型无论是Array,String还是Function,最终的__proto__指向都是这个位置。

明白了原型链,其实就能够理解很多的东西了,比如我们经常使用的instanceof判断类型和实现继承的一些方式。

instanceof

我们经常使用instanceof去判断一个数据的数据类型,其实A instanceof B的本质就是去判断A这个对象的原型链上是否有B.prototype。这样你就能很好的明白下面的一些结果了:

let bar  = 'merit'
let bar_s = new String('merit')
let bar_a = [1,2,3]
let bar_f = function(){console.log(1)}

bar instanceof Object //false
bar_s instanceof String //true
bar_a instanceof Array//true
bar_f instanceof Function//true

//任何对象类型的原型链终点都指向到Object的prototype
String instanceof Object//true
Array instanceof Object//true
Function instanceof Object //true
Object instanceof Object //true

Object instanceof Function //true
String instanceof Function//true
Array instanceof Function //true
Function instanceof Function //true
//对于最后一组,我们要知道{},[]创建对象或数组都是new Object()/new Array()的语法糖,而Object,Array本身这些构造器,又都是Function的一个实例。

既然对instanceof的原理理解了,我们也可以简单的写一个简易版的instanceof

//myInstanceof
function myInstanceof(A,B){
    while(A.__proto__){
        if(A.__proto__===B.prototype){
            return true
        }
        A=A.__proto__
    }
    return false
}

继承

通过对原型链的理解,我们就可以很好的实现继承了。

function Parent(value){
    this.tag='我是父对象'
    this.val = value
}
Parent.prototype.showVal = function(){console.log(this.val)}

组合继承

function Child(value,name){
    Parent.apply(this,value) //通过这一步可以保证子对象里面有父对象的值
    this.tag = '我是子对象' //会覆盖掉父对象的赋值
    this.name = name;
}
//接下来我们要保证子对象能调用父对象的方法
Child.prototype = new parent()
Child.prototype.constructor = Child 
let bar = new Child('111','merit')

虽然我不知道为什么这个名字叫做组合对象,但是原理还是很明显的,就是让子对象的prototype指向父对象的一个实例,然后利用这个实例的__proto__去调用父对象的方法,下面一张图应该能很详细的说明这一点

通过上面这个图,我们可以看出子对象的一个实例bar是如何调用父对象的方法的,但是我们也能够看出来一个问题,就是通过这种构建一个父对象的实例在中间进行过渡的方式,会造成内存的浪费,因为我们并不会使用到父对象里面的值,这时候我们就可以通过下面的继承方式来改善

寄生组合继承

function Child(value,name){
    Parent.call(this,value)
    this.tag='子对象'
    this.name = name
}
//这个会创造一个__proto__指向Parent.prototype的空对象
let childPrototype = Object.creat(Parent.prototype)
childPrototype.constructor = Child
Child.prototype = childPrototype

通过创建父对象实例而是通过Object创建空对象的方式继承,就很好的解决了上面的问题,可以说是一种比较完美的继承方案了。

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