英文:
same method or variable name in a javascript class behaves differently
问题
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);
// 为什么控制台返回父类中的方法变量 - "sss"?
英文:
class Parent{
method(){
console.log("Parent");
}
}
class Child extends Parent{
method(){
console.log("Parent");
}
}
var child = new Child();
console.log(child.method);
console return method in child class which is a expected behaviour.
class Parent{
method = "sss"
}
class Child extends Parent{
method(){
console.log("Child")
}
}
var child = new Child();
console.log(child.method)
why does the console return method variable - "sss" in Parent class ?
答案1
得分: 4
class Parent {
method = "sss";
}
是下面代码的简化形式:
class Parent {
constructor() {
this.method = "sss";
}
}
这意味着与以下方式存在一些重要的差异:
class Parent {
method() {
console.log("Parent");
}
}
-
在
method = "sss"
的变体中,method
将设置为创建的实例(new Child()
)的自有属性。child.hasOwnProperty("method") // => true
而定义普通方法
method() { console.log("Parent") }
将不会设置为实例的自有属性。相反,它会设置在原型链上。Parent.prototype.hasOwnProperty("method") // => true
-
构造函数代码仅在初始化实例时运行。这意味着
this.method = "sss"
将始终在你定义Parent
和Child
类之后运行(每当你使用new
创建实例时)。
最终的Child实例结构如下:
new Child()
// 返回
Child{ // 使用对象表示法描述的Child实例
// 自有属性
prop: "parent value", // 由Parent构造函数设置
// 使用__proto__(已弃用)属性描述的原型链
__proto__: {
// Child.prototype
prop() { return "child Value" },
method() { console.log("Child") },
__proto__: {
// Parent.prototype
method() { console.log("Parent") },
}
}
}
要获取更详细的信息,建议阅读MDN上的Public class fields页面。
英文:
class Parent {
method = "sss";
}
Is essentially a shortcut for:
class Parent {
constructor() {
this.method = "sss";
}
}
Meaning that there are some important differences with:
class Parent {
method() {
console.log("Parent");
}
}
-
In the
method = "sss"
variant,method
will be set as an own property of the created instance (new Child()
).child.hasOwnProperty("method") //=> true
Whereas defining a normal method
method() { console.log("Parent") }
will not be set as an own property of the instance. Instead it is set on the prototype chain.Parent.prototype.hasOwnProperty("method") //=> true
-
The constructor code only runs whenever you initialize an instance. Meaning that
this.method = "sss"
will always run after you've defined theParent
andChild
classes (whenever you create the instance withnew
).
<!-- begin snippet: js hide: false console: true babel: false -->
<!-- language: lang-js -->
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")`);
<!-- end snippet -->
The final Child instance structure looks like this:
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") },
}
}
}
For more detailed info I suggest reading through the MDN Public class fields page.
答案2
得分: 2
从MDN:
公共实例字段要么在基类的构造函数中(在构造函数体运行之前)添加到实例中,要么在子类中的super()返回后立即添加。
即它掩盖了方法,因为它是在构造函数运行时分配的。
child.method
是对象本身的属性(其值为字符串),这会掩盖原型上的method
,而原型上的method
是一个函数。
下面的代码演示了这一点。
您可以看到,在示例a
(您的代码)中,method
的字符串值是child
本身的属性,但您可以通过原型链来获取来自类的函数值。
在示例b
中(删除了公共实例字段),该方法存在并且可以被调用,但它不在child
本身上(因为它是类的实例,所以可以自动搜索原型链,因为它没有被掩盖)。
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();
英文:
From MDN
> Public instance fields are added to the instance either at construction time in the base class (before the constructor body runs), or just after super() returns in a subclass.
i.e. it masks the method because it is assigned around the time the constructor runs.
child.method
is a property (with a value that is a string) on the object itself. This masks the method
on the prototype which is a function.
The code below demonstrates.
You can see that in example a
(your code) the string value for method
is a property of child
itself, but you can dig through the prototype chain to get the function value from the class.
In example b
(with the public instance field removed), the method exists and can be called, but isn't on the child
itself (because its an instance of the class so it can search the prototype chain automatically because it isn't masked).
<!-- begin snippet: js hide: false console: true babel: false -->
<!-- language: lang-js -->
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();
<!-- end snippet -->
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论