将一个函数的原型设置为另一个函数的原型以进行子类化(使用 Object.setPrototypeOf()))

Setting prototype of a function as prototype of another function for doing Subclassing (with Object.setPrototypeOf()))

我不确定标题是否真的有意义,但是我正在尝试将函数原型设置为 "sub classes" 原型。

接下来的例子;

我尝试做的是:我有一个 userpaidUserpaidUsersubclassuser

用户工厂函数:

    function userCreator(name, score) {
      this.name = name;
      this.score = score;
    }
    userCreator.prototype.sayName = function(){console.log("hi");}
    userCreator.prototype.increment = function(){this.score++;}

并且我可以使用 new 关键字创建一个新用户。到目前为止一切顺利。

const user1 = new userCreator("Phil", 5);

现在,来到 Subclassing。 (对于我的示例,accountBalance 只是 paidUser 的一个愚蠢的 属性 特例)

    function paidUserCreator(paidName, paidScore, accountBalance){
      userCreator.call(this, paidName, paidScore);
      this.accountBalance = accountBalance;
    }

现在我想将 userCreatorprototype 设置为 paidUserCreator Factory Function

prototype

下面这行很完美,但我不太明白。 Object.create 函数应该创建一个空的 object 并且空的 objects __proto__ 必须是给定的参数。

paidUserCreator.prototype =Object.create(userCreator.prototype);

paidUserCreator.prototype.increaseBalance = function(){
  this.accountBalance++;
}

还有一点我不明白的是:

为什么下一行不起作用?

Object.setPrototypeOf(paidUserCreator, userCreator.prototype);

完成:

const paidUser1 = new paidUserCreator("Katarina", 4, 12);

PS:是的,我知道 Class 关键字更清晰易读,但我想学习如何以这种方式做到这一点。

从最后一个问题开始:

Why the following line doesn't work ?

Object.setPrototypeOf(paidUserCreator, userCreator.prototype);

会,但是你需要设置 paidUserCreator.prototype 的原型而不是 paidUserCreator 函数,这样当一个实例在 paidUserCreator.prototype 上寻找某些东西但没有找到它时, 它会寻找 userCreator.prototype.

function userCreator(name, score) {
  this.name = name;
}
userCreator.prototype.sayName = function() {
  console.log("hi");
}

function paidUserCreator(paidName, paidScore, accountBalance) {
  userCreator.call(this, paidName, paidScore);
}
Object.setPrototypeOf(paidUserCreator.prototype, userCreator.prototype);

let p = new paidUserCreator("Mark", 98, 200.5)
p.sayName()

paidUserCreator.prototype = Object.create(userCreator.prototype) 类似。 Object.create 创建一个新对象并将其原型设置为指向传入的对象。执行此操作时,您将替换 paidUserCreator.prototype 为原型链接到 userCreator.prototype 的新对象。需要注意的是,如果 paidUserCreator.prototype 上有任何您需要的东西,它将丢失,因为您要替换整个对象,而不仅仅是设置原型。

下面是一个可能会令您反感的例子:

function userCreator(name, score) {
    this.name = name;
}
userCreator.prototype.sayName = function(){console.log("hi");}

function paidUserCreator(paidName, paidScore, accountBalance){
    userCreator.call(this, paidName, paidScore);
}

// points to the paidUserCreator function
console.log(paidUserCreator.prototype.constructor)

// replace protoype with new object
paidUserCreator.prototype = Object.create(userCreator.prototype);

// now paidUserCreator.prototype has no constructor property
// so it defers to paidUserCreator
console.log(paidUserCreator.prototype.constructor)