最近学习JavaScript原型与原型链的时候,被这块知识烧得脑壳疼,prototype与__proto__混淆不清。网上各种图解,都画的好复杂,绕老绕去,不明所以,看得越来越糊涂。还是亲自动手敲敲,理解理解原型和原型链究竟是什么。
1、原型
(1)首先,什么是原型?
1>.定义:在JavaScript 中,每当定义一个对象的时候,对象中都会包含一些预定义的属性。其中每个函数对象都有一个prototype属性,这个属性就指向函数的原型对象。任何一个对象,都可以充当其他对象的原型;由于原型对象也是对象,所以它也有自己的原型。
2>.代码:
function f() {};
console.log(typeof f.prototype)
复制代码
3>.打印结果:
(2)示例:
1>.代码:
function Person(name) {
this.name = name;
}
Person.prototype.sex = 'male'
var Jack = new Person('Jack');
var Rose = new Person('Rose');
console.log(Jack.sex);
console.log(Jack.name);
console.log(Rose.sex);
console.log(Rose.name)
复制代码
2>.打印结果:
3>.以上代码,构造函数Person的prototype属性,就是实例对象Jack和Rose的原型对象。给原型对象上添加一个sex属性,可以看到它的实例对象都共享了该属性。
4>.根据上述这个构造函数Person,再来看看到底创建的实例对象都有什么属性。
5>.打印结果:
6>.从打印结果可以看出,函数对象Preson有一个prototype属性,这个属性就指向函数的原型对象__f()__,图中倒数第8行。而实例Jack是通过Person new出来的对象,所以Person充当了Person的原型对象,同样也是自己的原型对象。虽然有些绕,但是结合定义1>.和上述示例来看,就不难理解原型到底是什么。需要注意的是:每个对象都有 __proto__ 属性,但只有函数对象才有 prototype 属性。
7>.简单来讲,原型对象就像EVA机器人的设计图和零号机,那么在初号机,二号机,三号机等等,都是由这张设计图和零号机为基础建造出来的,即时它们各有特色,但它们身上的基本构造和属性都是可以在设计图和零号机身上找到,那么设计图和零号机就是它们的原型对象!
2、原型链
(1)那么,什么又是原型链?
1>.定义:简单来讲就是由多个原型组成的链,对象的__proto__它的是原型,而原型也是一个对象,也有__proto__属性,原型的__proto__又是原型的原型,就这样可以一直通过__proto__想上找,这就是原型链,当向上找找到Object的原型的时候,这条原型链就结束了。
2>.接着上面的示例,打印结果如下:
3>.根据打印结果可以得出,像Jack.__proto__.__proto__这样层层向上查询,先在实例本身中找,如果没找到就去它的原型中找,还没找到就再往上找,直到找到或抵达终点null。这样像链条一样的关系就是原型链。需要注意的是:所有对象的原型最终都可以上溯到Object.prototype,即Object构造函数的prototype属性。也就是说,所有对象都继承了Object.prototype的属性。这也是所有对象都有valueOf和toString方法的原因,因为这是从Object.prototype继承的。那么,Object.prototype对象有没有它的原型呢?回答是Object.prototype的原型是null。null没有任何属性和方法,也没有自己的原型。。所以原型链的尽头是null。如下图所示:
其实,跟着定义实际写写小demo,打印看看就能简单理解原型和原型链的概念,但知识是浩瀚如海的,本文只是粗浅的简单理解一下原型和原型链的基本知识,更深入的请期待下次,JS原型与原型链(二)。
3、参考资料
(1)MDN:继承与原型链
(2)阮一峰:对象的继承
(3)JavaScript高级程序设计(第三版)