关于JavaScript原型和原型链的简单理解

107 阅读2分钟

当谈到继承时,JavaScript 只有一种结构:对象。每个实例对象( object )都有一个私有属性(称之为 proto )指向它的构造函数的原型对象( prototype )。该原型对象也有一个自己的原型对象( proto ) ,层层向上直到一个对象的原型对象为 null 。根据定义,null 没有原型,并作为这个 原型链 中的最后一个环节。

几乎所有 JavaScript 中的对象都是位于原型链顶端的 Object 的实例。

在JavaScript中,将原型链作为实现继承的主要方法。其基本思想是利用原型让一个引用类型继承另一个引用类型的属性和方法。

一、例子

function SuperType() {
    this.property = true;
}
SuperType.prototype.getSuperValue = function() {
    return this.property;
}
function SubType() {
    this.subproperty = false;
}
// 继承了SuperType
SubType.prototype = new SuperType();
SubType.prototype.getSubValue = function() {
    return this.subproperty;
}
let instance = new SubType();
console.log(instance.getSuperValue())

以上代码定义了两个类型: SuperType 和 SubType 。每个类型分别都有一个方法和属性。其中 SubType 继承了SuperType,而继承是通过创建 SuperType 的实例,并将改实例赋值给 SubType.prototype 实现的。

二、确定实例和原型的关系

可以通过两种方式来确定原型和实例之间的关系

1、instance操作符

console.log(instance instanceof Object);	// true
console.log(instance instanceof SuperType);	// true
console.log(instance instanceof SubType);	// true

由于原型链的关系,我们可以说 instance 是 Object、SuperType、SubType中任何一个类型的实例

2、isProtoTypeOf() 方法

console.log(Object.prototype.isPrototypeOf(instance));	// true
console.log(SuperType.prototype.isPrototypeOf(instance));	// true
console.log(SubType.prototype.isPrototypeOf(instance));	// true

在这个方法中,只要是原型链中出现过的原型,都可以说是该原型链所派生的实例的原型。

三、prototype

每个 函数 都有一个 prototype 属性

function People() {
	this.age = 18
}
// 虽然写在注释里,但是你要注意:
// prototype是函数才会有的属性
People.prototype.name = 'Kevin';
var people1 = new People();
var people2 = new People();
console.log(people1.name) // Kevin
console.log(people2.name) // Kevin

四、proto

每一个JavaScript对象(除了 null )都具有的一个属性,叫 proto,这个属性会指向该对象的原型

function People() {
	this.age = 18;
}
var people = new People();
console.log(people.__proto__ === People.prototype); // true

五、constructor

每个原型都有一个 constructor 属性指向关联的构造函数 ,实例原型指向构造函数

function People() {
	this.age = 18;
}
console.log(People === People.prototype.constructor); // true

再来看一个例子

function People() {
	this.age = 18;
}

var people = new People();

console.log(people.__proto__ == People.prototype) // true
console.log(eople.prototype.constructor == People) // true
// 顺便学习一个ES5的方法,可以获得对象的原型
console.log(Object.getPrototypeOf(people) === People.prototype) // true

六、总结

function foo(){}
foo.prototype = {
  foo_prop: "foo val"
};
function bar(){}
var proto = new foo;
proto.bar_prop = "bar val";
bar.prototype = proto;
var inst = new bar;
console.log(inst.foo_prop);	// foo val
console.log(inst.bar_prop);	// bar val

读取 inst.foo_prop,从 inst 对象中找不到 foo_prop 属性就会从 inst 的原型也就是 bar.prototype 中查找,幸运的是我们找到了 bar_prop 属性,结果为 bar val。

文档链接


文档链接

MDN关于原型

简单理解原型及原型链