JavaScript中的原型

在学习原型之前,先看一下MDN文档中关于原型的描述:
JavaScript is often described as a prototype-based language — to provide inheritance, objects can have a prototype object, which acts as a template object that it inherits methods and properties from.

An object’s prototype object may also have a prototype object, which it inherits methods and properties from, and so on. This is often referred to as a prototype chain, and explains why different objects have properties and methods defined on other objects available to them.

什么意思呢,我们来看一下它的中文描述:
JavaScript 常被描述为一种基于原型的语言 (prototype-based language)——每个对象拥有一个原型对象,对象以其原型为模板、从原型继承方法和属性。原型对象也可能拥有原型,并从中继承方法和属性,一层一层、以此类推。这种关系常被称为原型链 (prototype chain),它解释了为何一个对象会拥有定义在其他对象中的属性和方法。

也就是说,我们可以通过原型这种机制,实现js中的继承。那么这种机制具体是什么样子呢?

在JavaScript中,函数可以有属性,每个函数都有一个特殊的属性,原型(prototype)。我们可以通过一种叫构造函数的特殊函数来定义对象和它们的特征。构造函数创建的实例通过原型链_proto_访问构造器中的属性和方法。
通过下边这个例子可以清楚的看到实例(testIns)的_proto_和它的构造函数(test)原型对象的关系:
JavaScript中的原型
默认情况下,所有函数的原型属性的_proto_指向的是window.Object.prototype。通过下边这段代码可以看到test.prototype中的指向是Object
JavaScript中的原型

可以通过这段代码来验证一下
JavaScript中的原型
那么Object.prototype._proto_指向的是哪里呢,它是没有指向的
JavaScript中的原型

由此可以看出构造函数和它的实例以及Object之间的关系是这样的
JavaScript中的原型
所以如果我们要访问一个对象的属性,那么会先从它本身寻找,如果本身不存在这个属性,则沿着_proto_一层一层网上找,不存在的属性最终为undefined。
如果一个实例修改了构造函数的prototype对象中的属性值,那么其他实例的值也会受影响
JavaScript中的原型
因此尽量避免直接在构造器的prototype中直接定义属性。
另外,上边代码可以看出,Object本身
JavaScript中的原型
JavaScript中的原型
另外,浏览器内置对象如Array、Date等的prototype的_proto_也指向Object.prototype。