关于原型和原型链

181 阅读2分钟

原型

每一个函数对象中都包含了prototype属性,该属性称为函数的原型,该属性是一个对象,默认情况下包含以下特点:

  1. 该对象是由 Object 构造函数创建的普通对象
  2. 对象包含constructor属性,该属性是一个函数,指向该函数本身
  3. 同时,prototype对象还可以包含其他可设置的方法和属性。

隐式原型

每一个对象都有一个属性__proto__,称为对象的隐式原型,该对象默认情况下有以下特点:

  1. 隐式原型默认情况下指向构造该对象的构造函数的显示原型prototype
function Person() {
    // ...
};
const person = new Person();
person.__proto__ === Person.prototype; // true
  1. 每一个函数都是构造函数 Function 的实例对象,所以fn.__proto__ === Function.prototype
function Person() {
    // ...
};
Person.__proto__ === Function.prototype; // true
  1. Function.prototype === Function.__proto__
  2. 每一个函数的原型同样是一个对象,对象都有__proto__属性,由于该对象的构造函数是 Object,所以,默认情况下可以得到Fn.prototype.__proto__ === Object.prototype
  3. 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]

相关图例

链条的全貌.jpg

原型链的应用

基础方法

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}');
}