原型
每一个函数对象中都包含了prototype属性,该属性称为函数的原型,该属性是一个对象,默认情况下包含以下特点:
- 该对象是由 Object 构造函数创建的普通对象
- 对象包含
constructor属性,该属性是一个函数,指向该函数本身 - 同时,
prototype对象还可以包含其他可设置的方法和属性。
隐式原型
每一个对象都有一个属性__proto__,称为对象的隐式原型,该对象默认情况下有以下特点:
- 隐式原型默认情况下指向构造该对象的构造函数的显示原型
prototype
function Person() {
// ...
};
const person = new Person();
person.__proto__ === Person.prototype; // true
- 每一个函数都是构造函数 Function 的实例对象,所以
fn.__proto__ === Function.prototype
function Person() {
// ...
};
Person.__proto__ === Function.prototype; // true
Function.prototype === Function.__proto__- 每一个函数的原型同样是一个对象,对象都有
__proto__属性,由于该对象的构造函数是 Object,所以,默认情况下可以得到Fn.prototype.__proto__ === Object.prototype Object.prototype.__proto__ === null
原型链
当我们访问一个对象的属性时,如果该对象本身不含该属性,则会去访问该对象的__proto__中是否有该属性,如果没有,则访问该对象的__proto__.__proto__,以此类推,直到找到该属性或方法或到达原型链的顶端(null)。这个过程称为原型链查找。
// -> 代表取隐式原型 xx.__proto__ 的过程
function Person() {
// ...
};
Person.prototype.sayHello = function() {
console.log('Hi,guys');
};
const person = new Person(); // person -> Person.prototype -> Object.prototype -> null
person.sayHello(); // 根据上述原型链,输出 Hi,guys
person.toString(); // 根据上述原型链,Person 的原型中不含此方法,则向上寻找 Object.prototype 中是否有此方法,结果输出 [object Object]
相关图例
原型链的应用
基础方法
W3C不推荐直接使用系统成员__proto__
Object.getPrototypeOf(对象)
获取对象的隐式原型
Object.prototype.isPrototypeOf(对象)
判断当前对象(this)是否在指定对象的原型链上
对象 instanceof 函数
判断函数的原型是否在对象的原型链上
Object.create(对象)
创建一个新对象,其隐式原型指向指定的对象
Object.prototype.hasOwnProperty(属性名)
判断一个对象自身是否拥有某个属性
应用
类数组转换为真数组
Array.prototype.slice.call(类数组);
实现继承
// -> 代表取隐式原型 xx.__proto__ 的过程
function Parent(age) {
this.age = age;
}
Parent.prototype.sayAge = function() {
console.log(`My age is ${this.age}`);
}
function Son(name, age) {
Parent.call(this, age);
this.name = name;
}
Son.prototype = Object.create(Parent.prototype); // 使得 Son.prototype -> Parent.prototype
Son.prototype.sayMyName = function() {
console.log('My name is ${this.name}');
}