原型?原型链?

1,915 阅读2分钟

2021.2.1更新

看到一张关系图感觉解释得更加清晰。

function Person (){  //构造函数
}
Person.prototype.name = '1';
var person = new Person(); // 实例对象, Person.prototype是该对象的原型

实例对象的原型 Person.prototype

实例对象的__proto__属性

结论

person.__proto__ === Person.prototype

额外,原型中的 constructor 属性, 指向构造函数。

function Person() {

}
console.log(Person === Person.prototype.constructor); //true

更新关系图

function Person() {

}

var person = new Person();

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

原型(Person.prototype / person__proto__表示)也是一个对象, 也可以用__proto__获取它的原型(原型的原型)

更新关系图

再进一步探索,Object.prototype的原型是什么?

Object.prototype.__proto__  // null, 即Object.prototype没有原型

更新关系图

由相互关联的原型组成的链状结构就是原型链,也就是蓝色的这条线。

学习链接:github.com/mqyqingfeng…


prototype 属性和__proto__属性

class F {
}

class C extends F {
}

C.__proto__ === F // true
C.prototype.__proto__ === F.prototype // true
  1. 子类的__proto__属性,表示构造函数的继承,总是指向父类。
  2. 子类prototype属性的__proto__属性,表示方法的继承,总是指向父类的prototype属性。

理解:

作为一个对象,子类的原型是父类; 即:C.__proto__ === F 
作为一个构造函数,子类的原型对象是父类的原型对象的实例。即:C.prototype.__proto__ === F.prototype

那么到底什么是prototype,什么是__proto__?

__ proto __

Every JavaScript object has a second JavaScript object (or null ,
but this is rare) associated with it. This second object is known as a prototype,
and the first object inherits properties from the prototype.

即:每个JS对象一定对应一个原型对象,并从原型对象继承属性和方法。

对象__proto__属性的值就是它所对应的原型对象。

var one = {x: 1};
one.__proto__ === Object.prototype // true ES规范定义对象字面量的原型就是Object.prototype

var two = new Object();
two.__proto__ === Object.prototype //往下阅读

那么prototype又是什么呢?

prototype

只有函数才有prototype属性

当你创建函数时,JS会为这个函数自动添加prototype属性,值是一个有 constructor 属性的对象。

而一旦你把这个函数当作构造函数(constructor)调用(即通过new关键字调用),那么JS就会帮你创建该构造函数的实例,实例继承构造函数prototype的所有属性和方法(实例通过设置自己的__proto__指向承构造函数的prototype来实现这种继承)。

function a() {} //构造函数a可以通过prototype来存储要共享的属性和方法
var b = new a(); //b是实例对象
b.__proto__ === a.prototype; //对象通过__proto__指向自己的构造函数的prototype

补充

JS是单继承的,Object.prototype是原型链的顶端,所有对象从它继承了包括toString等等方法和属性。

参考链接: wangdoc.com/es6/class-e… github.com/creeperyang…