【问题标题】:Javascript prototype property shadowedJavascript 原型属性被遮蔽
【发布时间】:2016-01-26 16:42:34
【问题描述】:

我对 Javascript 原型设计机制有些困惑。我有以下代码:

function Person () {
  this.name = "no name";
  this.setName = function (n) {
    this.name = n;
  }
}

function Student () {
  this.id = "123";
}
Student.prototype = new Person();

s = new Student();
s.setName("Klaus");

在代码执行后,对象 s 有两个名字。对象本身的名称“Klaus”和原型中的名称“no name”。我知道该属性被遮蔽并且工作正常,但这感觉不自然?!有没有更好的方法只使用原型的属性?

【问题讨论】:

  • 你为什么有this.setName = function (n) { this.name = n; } 构造?为什么不在Person() 函数之外写Person.prototype.setName = function (n) { this.name = n; }
  • @Teemu 据我了解,.setName 是在 s 的上下文中调用的,但它是学生。因此,该属性也将位于s 上(不在原型中)。最初,当将new Person 分配给Student 的原型属性时,该属性也会在其原型中创建。
  • 是的,但似乎 OP 明白这一点,他们说:“我知道 [prototype] 属性被遮蔽了”。但实际问题尚不清楚。
  • @Teemu 哦,是的,你是对的。我今天应该停止写答案了。
  • 你真正想要实现什么?在 s 的上下文中访问原型中的 names 自己的属性?

标签: javascript prototype shadowing


【解决方案1】:

您可以直接处理原型属性,但这会花费不成比例的努力,并且可能不被认为是最佳实践。相反,您可以在正确的 this 上下文中调用 Person 构造函数。

首先,强烈建议在分配给函数的prototype 属性时使用Object.create 而不是new 运算符。使用new 运算符,调用Person 构造函数,但在错误的this 上下文中。为了防止这种情况,您可以像这样链接它们:

Student.prototype = Object.create(Person.prototype);

相反,如果你想在 Student 内部调用原型链接 (Person) 的构造函数,你可以在构造函数中使用正确的 this 上下文 call 它:

function Student () {
  Person.call(this);
  this.id = "123";
}

另外,除非您想为每个实例创建一个函数,否则我会将 setName 函数移动到 Person[[Prototype]]

function Person () {
  this.name = "no name";
}

Person.prototype.setName = function (n) {
  this.name = n;
}

function Student () {
  Person.call(this); // Call the Person constructor
  this.id = "123";
}
Student.prototype = Object.create(Person.prototype);

s = new Student();
// s.name is 'no name'
s.setName("Klaus");
// s.name is 'Klaus'

或者,正如@Teemu 所提到的,您还可以将name 属性放在Person.prototype 上以将其用作默认值:

function Person () {
}

Person.prototype.setName = function (n) {
  this.name = n;
}

Person.prototype.name = "no name"; // Define the name directly

function Student () {
  Person.call(this); // you only need this, if there are other things happening in the Person constructor that you need as well
  this.id = "123";
}
Student.prototype = Object.create(Person.prototype);

s = new Student();
// s.name is 'no name'
s.setName("Klaus");
// s.name is 'Klaus'

【讨论】:

  • 如果我这样做,name 不再在原型中,而是创建对象的属性!这就是我想要的。只是Object.create() 而不是new
猜你喜欢
  • 2018-07-20
  • 2012-07-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-09-02
  • 2016-08-29
  • 2023-03-16
相关资源
最近更新 更多