JavaScript 类中的相同方法或变量名称的行为不同

same method or variable name in a javascript class behaves differently

提问人:MOHAMED SIKKANDAR AFZAL M 提问时间:7/24/2023 最后编辑:MOHAMED SIKKANDAR AFZAL M 更新时间:7/25/2023 访问量:93

问:

class Parent{
    method(){
        console.log("Parent");
    }
}
class Child extends Parent{
    method(){
        console.log("Parent");
    }
}
var child = new Child();
console.log(child.method);

子类中的控制台返回方法,这是预期的行为。

class Parent{
    method = "sss"
}
class Child extends Parent{
    method(){
        console.log("Child")
    }
}
var child = new Child();
console.log(child.method)

为什么控制台在 Parent 类中返回方法变量 - “sss” ?

JavaScript ES6-Class

评论

0赞 Wimanicesir 7/24/2023
Parent 有一个属性方法,即 'sss'。它还有一个名为“method”的函数。要调用函数,请使用 child.method()。
0赞 Quentin 7/24/2023
@Wimanicesir — JavaScript 不是这样工作的。方法只是一个属性,其中值是一个函数。此处的值是一个字符串。
0赞 Wimanicesir 7/24/2023
在 JavaScript 中,类可以同时具有方法和属性。使用 ES6 类语法创建类时,可以在类中定义方法和属性。不是因为你的方法就像一个道具,你不能称它为方法。我认为用这些术语来表达更清楚。
2赞 Quentin 7/24/2023
@Wimanicesir——真的不是。在 JS 中,“Method”是给定属性的名称,其中值是函数。仅此而已。
1赞 Quentin 7/24/2023
@Wimanicesir——我们陷入了术语的泥潭。Method 是值为函数的属性的有用术语。假装方法在某种程度上是特殊的是没有用的。它们肯定没有提供一种同时同时成为字符串和函数的方法。(我们不要讨论向函数添加方法,然后将其赋值为属性值的可能性,因为这不是问题所在)。child.methodtoString

答:

2赞 Quentin 7/24/2023 #1

来自 MDN

公共实例字段在基类的构造时(在构造函数主体运行之前)或在子类中返回 super() 之后)添加到实例中。

即,它屏蔽了方法,因为它是在构造函数运行时分配的。

child.method是对象本身的属性(其值为字符串)。这掩盖了原型上的一个功能。method


下面的代码演示了。

您可以看到,在示例(您的代码)中,字符串值是其自身的属性,但您可以挖掘原型链以从类中获取函数值。amethodchild

在示例中(删除了公共实例字段),该方法存在并且可以调用,但不在本身上(因为它是类的实例,因此它可以自动搜索原型链,因为它没有被屏蔽)。bchild

const a = () => {
  class Parent {
    method = "sss"
  }
  class Child extends Parent {
    method() {
      console.log("Child")
    }
  }
  var child = new Child();
  console.log("a: " + child.hasOwnProperty('method'));
  Object.getPrototypeOf(child).method();
};

a();

const b = () => {
  class Parent {}
  class Child extends Parent {
    method() {
      console.log("Child")
    }
  }
  var child = new Child();
  console.log("b: " + child.hasOwnProperty('method'));
  child.method();
};

b();

评论

0赞 codingStarter 7/24/2023
但它也发生在子类中——按照同样的原则,它应该发生在父亲字段之后?
0赞 Quentin 7/24/2023
方法不是公共实例字段。
1赞 codingStarter 7/24/2023
“方法只是一个属性”——这就是你之前说的
0赞 Quentin 7/24/2023
@codingStarter — 是的,方法只是属性(以函数作为其值),但 OP 在此处分配方法的方式并不能使其成为公共实例字段。
0赞 codingStarter 7/24/2023
@Quentin谢谢,我也查了一下 - 如果您使用 method = function(){},它将是一个实例字段,也许为了清楚起见而添加它
4赞 3limin4t0r 7/24/2023 #2
class Parent {
    method = "sss";
}

本质上是以下方面的快捷方式:

class Parent {
    constructor() {
        this.method = "sss";
    }
}

这意味着与以下方面存在一些重要区别:

class Parent {
    method() {
        console.log("Parent");
    }
}
  1. 在变体中,将设置为创建的实例的自有属性()。method = "sss"methodnew Child()

    child.hasOwnProperty("method") //=> true
    

    而定义普通方法不会设置为实例的自有属性。相反,它被设置在原型链上。method() { console.log("Parent") }

    Parent.prototype.hasOwnProperty("method") //=> true
    
  2. 构造函数代码仅在初始化实例时运行。这意味着在定义 and 类后(每当您使用 创建实例时)将始终运行。this.method = "sss"ParentChildnew

class Parent {
    prop = "parent value";
    // aka
    // constructor() {
    //   this.prop = "parent value";
    // }
    method() {
        console.log("Parent");
    }
}

class Child extends Parent {
    prop() {
      return "child Value";
    }
    method() {
        console.log("Child");
    }
}

const child = new Child();

const log = (jsString) => console.log(jsString, '//=>', eval(jsString));
log(`child.hasOwnProperty("prop")`);
log(`child.hasOwnProperty("method")`);
log(`Parent.prototype.hasOwnProperty("prop")`);
log(`Parent.prototype.hasOwnProperty("method")`);

最终的子实例结构如下所示:

new Child()
// returns
Child{ // Child instance depicted using object notation
  // own properties
  prop: "parent value", // set by the Parent constructor

  // prototype chain depicted using the __proto__ (deprecated) property
  __proto__: {
    // Child.prototype
    prop() { return "child Value" },
    method() { console.log("Child") },

    __proto__: {
      // Parent.prototype
      method() { console.log("Parent") },
    }
  }
}

有关更多详细信息,我建议通读 MDN 公共类字段页面。