let o1.prototype = Object.create(o2.prototype) 和 o1.prototype = o2.prototype 有什么区别?

What is the difference let o1.prototype = Object.create(o2.prototype) and o1.prototype = o2.prototype?

所以我想了解 o1.prototype = Object.create(o2.prototype)o1.prototype = o2.prototype 之间的区别。

根据 this question 的回答,前者通过 obj1.prototype 的原型将 obj2.prototype 设置为 obj1.prototype,但我很难理解为什么你会想要那个(例如,新原型的原型只是 Object.prototype,因为原型是一个没有进一步继承的对象)。此外,它似乎并不像该问题的答案一直暗示的那样有效。

在下面的代码中,例如:

function o1(){}
o1.prototype.test = "test";
function o2(){}
o2.prototype = Object.create(o1.prototype);
let instance1 = Object.create(o1);
console.log(o2.prototype.test, instance1.prototype.test);

o2.prototype.testinstance1.prototype.test 都打印 "test"。因此,将 o2 直接分配给 Object.create(o1.prototype) 或将 o2 的原型设置为 Object.create(o1.prototype) 似乎并不重要。

此外,如果我理解正确,根据链接问题中的答案,如果 o1 为空(在本例中为空),则设置 o2 = o1 将是与设置 o2 = Object.create(o1) 相同,也与

相同
function o1(){};
function o2(){};
o2.prototype = o1.prototype;

这三者之间有什么显着差异吗?另外,如果 o2.prototype = Object.create(o1.prototype) 创建一个 empty 对象,并且 o1.prototype 的原型作为它自己的原型,如果 o1 的原型不为空,那么o1 的原型成员如何导入到 o2 的原型中?

如果您直接将 Parent.prototype 分配给子对象的原型,它们将指向同一个对象。因此,如果您添加一个仅适用于子 class 的方法,父对象也将可以访问它们,因为 Parent.prototype === Child.prototype

示例:

function Animal() {};
Animal.prototype.Eat = function() {
  console.log("Eating")
}

function Human() {};
Human.prototype = Animal.prototype; // both point to the same object

Human.prototype.Drive = function() {
  console.log("Driving")
}

var animal = new Animal();
var human = new Human();

animal.Eat();
human.Eat();

animal.Drive(); // Animals shouldn't be driving
human.Drive();

console.log("animal instanceof Human: ", animal instanceof Human) // true

如果您改用 Object.create(Animal.prototype),它会创建一个新对象,并将 [[Prototype]](同样,但已弃用,__proto__)设置为 Anima.prototype。因此,如果在 Human.prototype 上找不到任何方法,它将 退回到 Animal.prototype(在本例中为 Eat

function Animal() {};
Animal.prototype.Eat = function() {
  console.log("Eating")
}

function Human() {};
Human.prototype = Object.create(Animal.prototype)
Human.prototype.constructor = Human; // update the constrcutor

Human.prototype.Drive = function() {
  console.log("Driving")
}

var animal = new Animal;
var human = new Human;

animal.Eat();
human.Eat();
human.Drive();

try {
   // This will throw an error because Animal.prototype doesn't have a Drive method
  animal.Drive();
} catch {
  console.log("Animals can't drive")
}

console.log("animal instanceof Animal: ", animal instanceof Animal) // true
console.log("animal instanceof Human: ", animal instanceof Human) // false
console.log("human instanceof Animal: ", human instanceof Animal) // true
console.log("human instanceof Human: ", human instanceof Human) // true

console.log(animal.constructor)
console.log(human.constructor)

当您访问 human.Eat() 时,该方法首先会直接在 human 对象下查找。如果找不到,将在其原型 Human.prototype 中搜索。

Object.getPrototypeOf(human) === Human.prototype;

因为那里没有找到 Eat 方法,所以将在 Human.prototype 的原型中查找该方法,即 Animal.prototype

Object.getPrototypeOf(Human.prototype) === Animal.prototype

这里找到方法,将执行。


假设您要使用 human.hasOwnProperty('eyes')。它通过与上述类似的链。如果在 human 对象 Human.prototypeAnimal.prototype 上找不到 hasOwnProperty,它将检查 Object.prototpye 内部,因为

Object.getPrototypeOf(Animal.prototype) === Object.prototype

Object.prototype 有一个名为 hasOwnProperty 的方法,它将被执行