原型和原型链作为Javascript里的一座大山,那么什么是原型,什么是原型链呢?弄明白它是每个前端工程师必经的过程.我希望能用最简单直白的语言让大家都能看明白原型和原型链,现在让我们窥探一下原型和原型链的过程和原理.
原型
什么是原型:
在Javascript中是使用构造函数来创建一个对象的.每一个构造函数的内部都有一个 prototype 属性,它的属性值是一个对象,这个对象包含了可以由该构造函数的所有实例共享的属性和方法.当使用构造函数新建一个对象后,在这个对象的内部将包含一个指针,这个指针指向构造函数的 prototype 属性对应的值.
下面用一段代码举个例子.首字母大写的代表构造函数,小写的代表普通函数.prototype代表构造函数的原型,__proto__代表实例对象的原型.
let a = new Fun() //用构造函数 Fun 创建对象 a
FunObj{
属性1:值1,
属性2:值2,
.
.
prototype:{
fun1(),
fun2()
}
}
aObj{
属性1:值1,
属性2:值2,
.
.
__proto__:{
fun1(),
fun2()
}
}
原型链
当访问一个对象的属性时,如果这个对象内部不存在这个属性,那么它就会去它的原型对象里找这个属性,这个原型对象又会有自己的原型,于是就这样一直找下去,也就是原型链的概念
通过这张图我们可以注意到,构造函数Foo的原型prototype 和 构造函数Foo所创建出来的对象实例f1,f2的原型__proto__是一样的都指向Foo().prototype.
这里我们可以继续思考,往下探索一下,既然Foo().prototype也是一个对象,那是不是Foo().prototype也有自己的对象原型__proto__呢.答案是肯定的,图中我们也可以看到Foo().prototype的对象原型__proto__指向的是Object.prototype. Object作为最顶端的构造函数,可以看到所有的对象都会通过原型链指向它.这就是为什么新建的对象为什么能够使用 toString() 等方法的原因.
但是我们可以发现Object.prototype也有自己的__proto__ 但是却指向的是null,null为原型链的终点.
注意!!!
那么这里还个问题,细心的小伙伴已经发现了,构造函数有自己的原型prototype,但是构造函数也是对象啊,构造函数也有没有__proto__呢.答案是有的.因为每个 JavaScript 函数实际上都是一个 Function 对象。运行 function(){}).constructor === Function // true 便可以得到这个结论。
而且通过图我们也可以发现 Foo的__proto__指向Function.prototype,而且这里还有个特例,上文也说明了每个 JavaScript 函数实际上都是一个 Function 对象,所以Function的构造函数原型prototype和对象原型__proto__都是指向同一个Function.prototype.
结尾
希望看到这里的小伙伴已经对原型和原型链的过程有了一定的了解,同时也欢迎各位读者对本片文章提供建议.一起共同努力共同成长.