原型
每个函数都有一个prototype属性,这个属性称之为原型。因为这个属性的值是个对象,所以也称之为原型对象。作用就是:存放一些属性和方法,共享给实例对象使用;在JS中实现继承。
const arr = new Array(1, 2, 3);
arr.reverse(); // 翻转
arr.sort(); // 排序
arr.filter(); // 过滤
这些方法都是挂载到 Array.prototype 上的,共享给 Array 的实例去使用的。
为什么实例可以使用原型上的方法?
__proto__(隐式原型)
每个对象都有一个__proto__属性,这个属性指向它的原型对象。
const arr = new Array(1, 2, 3);
console.log(arr.__proto__ === Array.prototype);
// true 指向同一块内存
原型链
原型对象也是对象,也有一个__proto__属性,这个属性指向原型对象的原型对象,这样一层一层形成的链式结构称之为原型链(__proto__可以理解为原型链的连接点),最顶层找不到则返回null。
看以下代码一目了然:
Object.prototype.name = 'object.prototype';
function Parent() {
this.name = 'parent';
}
Parent.prototype.name = 'parent.prototype';
function Child() {
this.name = 'child';
}
Child.prototype = {
name: 'child.prototype',
__proto__: new Parent()
}
const child = new Child();
console.log(child.name);
// child
首先会在自身去查找
Object.prototype.name = 'object.prototype';
function Parent() {
this.name = 'parent';
}
Parent.prototype.name = 'parent.prototype';
function Child() {
// this.name = 'child';
}
Child.prototype = {
name: 'child.prototype',
__proto__: new Parent()
}
const child = new Child();
console.log(child.name);
// child.prototype
如果自身的构造函数中没有,就会去它的原型上查找
Object.prototype.name = 'object.prototype';
function Parent() {
this.name = 'parent';
}
Parent.prototype.name = 'parent.prototype';
function Child() {
// this.name = 'child';
}
Child.prototype = {
// name: 'child.prototype',
__proto__: new Parent()
}
const child = new Child();
console.log(child.name);
// parent
如果它的原型上也没有,就会去 Parent 的构造函数中查找
Object.prototype.name = 'object.prototype';
function Parent() {
// this.name = 'parent';
}
Parent.prototype.name = 'parent.prototype';
function Child() {
// this.name = 'child';
}
Child.prototype = {
// name: 'child.prototype',
__proto__: new Parent()
}
const child = new Child();
console.log(child.name);
// parent.prototype
如果 Parent 的构造函数中也没有,继续在 Parent 的原型上查找
Object.prototype.name = 'object.prototype';
function Parent() {
// this.name = 'parent';
}
// Parent.prototype.name = 'parent.prototype';
function Child() {
// this.name = 'child';
}
Child.prototype = {
// name: 'child.prototype',
__proto__: new Parent()
}
const child = new Child();
console.log(child.name);
// object.prototype
// Object.prototype.name = 'object.prototype';
function Parent() {
// this.name = 'parent';
}
// Parent.prototype.name = 'parent.prototype';
function Child() {
// this.name = 'child';
}
Child.prototype = {
// name: 'child.prototype',
__proto__: new Parent()
}
const child = new Child();
console.log(child.name);
// undefined
有点像Java类加载中的双亲委派机制,不过是反过来了。