前言
记一下JS原型的知识
原型
假如有下面的代码
1 2 3 4 5 6
| function Person(name = "sena", age = 16) { this.name = name; this.age = age; }
let person = new Person();
|
原型的关系是这样的

原型链
通过 __proto__
作为桥梁连接起来的一系列原型就是原型链

1 2 3 4 5 6 7 8 9 10
| function Person(name = "sena", age = 16) { this.name = name; this.age = age; }
let person = new Person();
console.log("person的原型", Reflect.getPrototypeOf(person)); console.log("object的原型", Reflect.getPrototypeOf({})) console.log("object原型的原型",Reflect.getPrototypeOf(Reflect.getPrototypeOf({})));
|
输出结果是

继承
es6为我们提供了非常好的继承模式
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| class Person { constructor(name = "sena", age = 16) { this.name = name; this.age = age; } }
class Worker extends Person { constructor(name = "sena", age = 16) { super(name, age); } } Worker.prototype.company = "Google"
let worker = new Worker(); let person = new Person();
console.log("worker的原型", Reflect.getPrototypeOf(worker)); console.log("worker原型的原型", Reflect.getPrototypeOf(Reflect.getPrototypeOf(worker))) console.log("worker原型的原型和person的原型比较", Reflect.getPrototypeOf(Reflect.getPrototypeOf(worker)) === Reflect.getPrototypeOf(person)); console.log("person的原型", Reflect.getPrototypeOf(person)); console.log("object的原型", Reflect.getPrototypeOf({})) console.log("object原型的原型",Reflect.getPrototypeOf(Reflect.getPrototypeOf({})));
|

我们可以从babel转化后的代码中看出这种继承是怎么实现的
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50
| "use strict";
function _inheritsLoose(subClass, superClass) { subClass.prototype = Object.create(superClass.prototype); subClass.prototype.constructor = subClass; _setPrototypeOf(subClass, superClass); }
function _setPrototypeOf(o, p) { _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return _setPrototypeOf(o, p); }
var Person = function Person(name, age) { if (name === void 0) { name = "sena"; }
if (age === void 0) { age = 16; }
this.name = name; this.age = age; };
var Worker = function (_Person) { _inheritsLoose(Worker, _Person);
function Worker(name, age) { if (name === void 0) { name = "sena"; }
if (age === void 0) { age = 16; }
return _Person.call(this, name, age) || this; }
return Worker; }(Person);
Worker.prototype.company = "Google"; var worker = new Worker(); var person = new Person();
|
概括一下就是
- 创建一个父类型的对象
temp
,并且把对象的constructor
属性设置成子类型的构造函数
- 把创建的父类型对象
temp
设置成子类型构造函数的prototype
- 把子类型构造函数的
__proto__
指向父类型
自己写一个inherit
函数可以写成这样
1 2 3 4 5
| function inherit(sub, sup) { sub.prototype = Object.create(sup.prototype); sub.prototype.constructor = sub; Object.setPrototypeOf(sub, sup); }
|
奇怪的东西增加了
有这么一张非常有趣的图

大部分东西都在上面讲过了
只有一个东西要提一下,那就是所有函数的__proto__
都指向Function.prototype
1
| Object.__proto__ === Function.prototype
|

那就随便提提这个,对象的prototype
指向undefined

为什么要有super
看图看图,super
初始化了对象并且使用父构造函数来为this
绑定属性


后记
别骂了,我自己都觉得水)
FAQ & Ref
图解原型和原型链