使用或不使用 .prototype 定义 class

Defining a class with or without the .prototype

在没有使用class关键字的情况下,下面两种构造继承对象的方式有什么区别?在第一个中,我在 .prototype 上附加了东西,而在第二个中,我直接在函数上进行了附加。会有什么区别?

function basicPrototype(){};
basicPrototype.prototype.sayHi = function(name){
    console.log("Hello,", name);
}

function basicConstructor() {
    return this; // make sure to pass it a this
}

let basicObj = basicConstructor.call(Object.create(basicPrototype.prototype));
basicObj.sayHi("Tommy");

并删除两行的 .prototype

function basicPrototype(){};
basicPrototype.sayHi = function(name){
    console.log("Hello,", name);
}

function basicConstructor() {
    return this; // make sure to pass it a this
}

let basicObj = basicConstructor.call(Object.create(basicPrototype));
basicObj.sayHi("Tommy");

两个示例的代码都可以清理,因为 basicConstructor.call 对不久前通过 Object.reate 创建的传递对象没有任何影响。

此外 basicConstructor 尽管它的名字根本不是构造函数,因为它从未创建实例,因为它从未被 new 调用过。 (它也没有任何实现,既不在函数体内也不在自己的原型实现中。)因此 basicConstructor 更像是一个(身份?)function/method 其中 returns 其调用时间的引用this 上下文。所以可有可无。

从以上评论...

Thus, the real question is ... "What is the difference in between the object creation of Object.create(basicPrototype.prototype) and Object.create(basicPrototype)?"

很明显,前者创建一个新对象,并将 basicPrototype.prototype 设置为新对象的原型,后者创建一个对象,其函数 basicPrototype 设置为新对象的原型...

... 这意味着这两种情况的 calling/sending sayHi on/to basicObj 在技术上是相同的。由于 basicObj 没有这样一个自己的 属性,因此将查找两个对象的原型链。

这两种方法都会立即被发现,因为两个原型都以 sayHi 作为它们自己的 属性,这对于前一种情况来说很明显,但(对于某些人来说)对于后一种情况可能会令人惊讶。 (我不得不亲自查看 twice/three 次并再次核对。)第二个示例确实实现了 sayHi 并将其直接 属性 分配给函数 basicPrototype。因此,对于后一种情况,该函数主要充当转储对象,就像 basicPrototype.prototype 对前一种情况所做的那样。

作为最后的结论,可以说。示例代码是一个棘手的脑筋急转弯,其中不涉及任何 class 相关(就构造函数和构造函数原型而言)。一切都通过 class/constructor 更少的 Object.create 替代来实现。剩下的只是棘手的、无害的混淆。