JavaScript 构造函数 - 了解继承



我正在学习如何使用构造函数在JavaScript中实现OOP,并且我对如何创建子类型感到困惑。

我目前的理解是,新关键字是在幕后执行以下操作:

  • 创建空this对象
  • this对象的__proto__属性设置为指向构造函数上的原型属性
  • 返回this对象

这就是为什么我们不必从构造函数显式返回对象,new关键字为我们执行此操作。

在下面的示例中,我正在创建User类型的PaidUser子类型:

function User(name) {
this.name = name;
}
function PaidUser(name, balance) {
User.call(this, name);
this.balance = balance;
}

在我看到的示例之后,我从PaidUser类型中的User类型属性进行扩展,并在User构造函数中设置this的上下文,以指向带有User.call(this,...)的词法this

我的困惑是User.call()如何影响new关键字从PaidUser构造函数隐式返回的内容?

例如,在PaidUser构造函数中,我将this.balance属性定义为this对象,现在我的理解是使用new关键字调用时将从PaidUser构造函数返回的this对象。User.call(this, name)如何返回或影响从PaidUser构造函数返回的对象。

目前根据我的理解,这就是幕后发生的想象:


function PaidUser(name, balance) {
this = {
__proto__:PaidUser.prototype
};
this.balance = balance;
User.call(this, name); // {this.name:name}; //lexical this
// why is the object returned from User.call() just floating around
// neither assigned to a variable or returned ?
return this;  // how does this.name ever become part of the returned object?
}

我非常感谢有关调用PaidUsernew构造函数时 关键字所采取的步骤的任何帮助和解释。

非常感谢和赞赏。

我的困惑是User.call()如何影响PaidUser构造函数中new关键字隐式返回的内容?

理解这种情况发生的关键是了解传递给函数的对象可能会在函数外部受到影响:

//function that takes an object and mutates it
function fn(o) {
o.hello = "universe";
}
//a simple object
var obj = {
hello: "world"
};
console.log("before calling the function", obj);
//call the function with the object
fn(obj);
console.log("after calling the function", obj);

因此,对象可以在函数内部发生变异,也会在函数外部影响它们。

当您调用User构造函数的主体this.name = nameUser.call(this, name);这会改变this上下文时,也会发生这种情况。由于this上下文是一个对象,因此它将在函数外部发生突变。由于它有效地改变了new PaidUserthis上下文,因此代码会这样做:

function PaidUser(name, balance) {
this.name = name; //contents of User.call(this, name);
this.balance = balance;
}

所以,它实际上没有看起来那么神奇。new关键字在整个过程中扮演的唯一部分是new PaidUser将创建一个新对象并将其设置为this上下文。您可以通过执行以下操作来模拟类似的效果:

function User(name) {
this.name = name;
}
function PaidUser(name, balance) {
User.call(this, name);
this.balance = balance;
}
var obj = {};
PaidUser.call(obj, "Fred", 1234);
console.log(obj);

这不会做new关键字所做的一切 - 它不会设置原型,不会让构造函数隐式返回this,但它仍然创建一个新对象并将其通过所有赋值。由于我们引用了对象,我们可以在之后检查它,并看到代码确实有效地完成了obj.name = nameobj.balance = balance

最新更新