它是什么
数据的继承关系。可以想象成一根连接各个原型节点的链条,一端是被继承者,一端是继承者。继承者拥有被继承者的所有属性和方法。
原型链的特点
原型链的顶端是null。当某个节点的原型是null时,原型链结束,没有再上一层的原型了。
所有数据都默认继承自Object.prototype,无论中间有多少层原型。
它解决了什么问题
因为原型链的存在,数据之间可以共享属性和方法,避免重复定义,提高了内存效率。
js
const obj = { name: "张三" };
console.log(obj.hasOwnProperty("name")); // true
对象obj的hasOwnProperty()就是继承自Object.prototype,因此无需为对象obj单独实现hasOwnProperty()也可以使用。
js
console.log(Object.prototype);
打印Object.prototype可以看到:

它是怎么工作的
访问属性或方法
当访问某个对象的属性或方法时,会先检查对象自身是否有该属性或方法,如果有,直接返回;如果没有,会继续检查原型链上的节点,直到找到或到达原型链的终点。如果到达原型链的终点,还没有找到,就会返回undefined。

需要额外注意的是,对象的方法中的this指向的是调用方法的对象,而不是原型链上的对象。
js
const parent = {
name: 'parent',
sayName() {
console.log(this.name);
console.log("this:", this);
}
}
const child = {
__proto__: parent
}
child.sayName(); // parent this: {}
parent.sayName(); // parent this: {name: 'parent'}
在这个例子中,虽然执行结果都是parent,但this指向不同。当执行child.sayName()时,虽然child对象无sayName(),真正调用的是原型parent的sayName(),但this指向的是child,这一点从打印结果this: {}可以看出。
创建原型的不同方式
使用语法结构
js
const parent = {
age: 18,
};
const child = { name: "child", __proto__: parent };
console.log(child.age); // 18
在字面量中,可以使用__proto__声明对象的原型。需要注意的是,__proto__的值应为对象类型,虽然值为非对象类型时不会报错,但也不会生效。例如:
js
const child = { name: "child", __proto__: 3 };
console.log(child);
通过打印结果可以看到,child的原型为Object.prototype: 
使用构造函数
js
function People(name, age) {
this.name = name;
this.age = age;
}
People.prototype.addAge = function (value) {
this.age += value;
};
const someOne = new People("张三", 18);
console.log(someOne);
当使用构造函数创建一个实例后,构造函数的原型会自动作为该实例的原型------构造函数People的原型包含一个addAge(),someOne的原型也包含addAge()。 
使用Object.create
js
const parent = { name: "parent" };
const child = Object.create(parent);
console.log(child.name); // parent
使用类
js
class Parent {
constructor(name) {
this.name = name;
}
}
class Child extends Parent {
constructor(name) {
super(name);
this.age = 18;
}
}
const child = new Child("child");
console.log(child);
通过打印结果可以看到,整个原型链为child --> Child.prototype --> Parent.prototype --> Object.prototype --> null。

使用Object.setPrototypeOf()
js
const parent = { name: "parent" };
const child = { age: 18 };
Object.setPrototypeOf(child, parent);
console.log(child.name); // parent
使用__proto__访问器
js
const parent = { name: "parent" };
const child = {};
child.__proto__ = parent;
console.log(child.name);
需要注意的是,__proto__访问器是非标准的,且已经被废弃,最好使用Object.setPrototypeOf()创建原型。