来自灵魂的拷问
你的原型链是怎么了解的,原型链主要解决什么问题?
路人回答
原型?链?铁链?原型不懂,异形我看过。
小白回答
在JavaScript中,每个函数都有一个prototype属性,这个属性指向这个函数的原型对象
老鸟回答
JavaScript是一门面向对象的语言,但他的作者其实是一个函数式语言的忠实粉丝,奈何才华不能果腹,网景公司让他在两周内,模仿Java写一个面向对象的语言,虽然折腰,但作者的身体还是很诚实,所以JavaScript看起来又像是一个面向函数式的语言。
这点从JavaScript的对象上就可以看出来,他的实现方式真的是非常不同。
JavaScript每个对象都连接到一个原型对象,并且它可以从中继承属性,所有通过对象字面量创建的对象都会连接到Object.prototype,它是JavaScript中的标配对象。也就是说,JavaScript的继承是通过拷贝原型而实现的。最重要的是,他没有类……,对的,JavaScript没有类这个概念,所以你对原型对象上增加属性,会影响到所有使用这个原型进行继承的对象上。
所以你要理解原型链,你就得了解原型,了解原型,你就得了解下面一些概念
- prototype:是函数的一个属性,指向这个函数的原型对象
- proto:每个非空对象,都有一个__proto__属性,用来指向该对象的原型
- constructor:每个原型对象都有一个constructor属性,指向构造函数
这样说,你可能还是云里雾里,我们直接上例子吧:
例子
function Persion() {}
Person.prototype.name = 'jack'
var person = new Person()
console.log(person.name) //jack
如果你学过Java,你会疑惑,不是说JavaScript没有类的概念吗?那Persion是什么?嗯,它不叫类,它叫构造函数……,而person叫构造函数Persion的实例化对象,而Person.prototype叫原型对象……
一图胜千言,我们直接上图吧:
由于原型对象也是对象,也是有__proto__属性的,所以他的__proto__也指向了自己的原型对象,一直往上,就形成了原型链
那原型链有啥作用呢?
由于读取实例的属性时,如果找不到,就会查找与对象关联的原型中的属性,如果还查不到,就去找原型的原型,一直找到最顶层为止。由于每个构造函数都有一个原型对象,原型对象都包含一个指向构造函数的指针,而实例都包含一个指向原型对象的内部指针。那么假如我们让原型对象等于另一个类型的实例,结果会怎样?显然,此时的原型对象将包含一个指向另一个原型的指针,相应地,另一个原型中也包含着一个指向另一个构造函数的指针。假如另一个原型又是另一个类型的实例,那么上述关系依然成立。如此层层递进,就构成了实例与原型的链条。这就是所谓的原型链的基本概念。
嗯,上面那段话来自JavaScript红宝书,如果感觉拗口,下面画个图,参考下:
这边注意下
- 由于Function构造函数的构造函数就是它本身,所以它是可以被作为实例化对象的角色 来访问的,也就是说Function.proto===Function.prototype,所以图上Function的指向是没有问题的
- 任何函数都继承Function的属性和方法,而Function是内置构造函数,也是对象,对象都继承Object的所有属性和方法