基本说明
- 所有引用类型(函数,数组,对象)都拥有
__proto__
属性(隐式原型) - 所有函数拥有
prototype
属性(显式原型)(仅限函数) - 原型对象:拥有
prototype
属性的对象,在定义函数时就被创建。 - 每一个实例都有隐式原型(
__proto__
),并指向 创建它的构造函数的 显式原型(prototype
)。
代码中原型和原型链展示
-
主要有三个概念,
__proto__
(隐式原型)prototype
(显示原型)constructor
(构造函数)。 -
所谓原型就是
person.__proto__
和Person.prototype
, 二者是等同的。 -
所谓原型链就是通过隐式原型
__proto__
一层一层串联起来的链子。 -
原型链一直查到null为止。
-
三者之间的关系如下代码所示:
// 声明一个构造函数 Person function Person (name = '张三') { this.name = name; }; // 可以给函数的原型上添加方法,为Person添加一个方法 getName Person.prototype.getName = () => { return 'getting name'; }; // 创建一个Person实例 let person = new Person(); console.log( person ); // 实例的__proto__指向构造函数的prototype,构造函数的显式原型的constructor指向的是构造函数。 // 构造函数内部没有getName, 会向其父级寻找,找到后继承该方法。 实例的 __proto__ 等同于 函数的 prototype person.getName(); // 'getting name'; person.__proto__ === Person.prototype; person.__proto__.constructor === Person; person.__proto__.__proto__ === Object.prototype; person.__proto__.__proto__.constructor === Object; person.__proto__.__proto__.__proto__ === null; // 如上所示,实例的__proto__指向的就是函数的原型,原型的constructor属性则将其指向构造函数。通过__proto__不断一级一级向上而形成的链子,就被成为原型链。 // 逐层向上查找,直到null结束,如扔没有找到,则返回undefined。
原型和原型链的关系图如下所示:
拓展原型链的四种方法
// 方式一: Object.create() 创建一个对象,将其__proto__指向 proto
Object.create(proto, [ properties ]);
// 方式二: Object.setPrototypeOf(obj, prototype); prototype 设置为 obj 的 __proto__
// 方式三: __proto__;
obj1.__proto__ = obj2;
// 方式四: 构造函数创建
function Person(){};
Person.prototype.getName = () => { console.log( 'getName' ) };
相关文章: