Javascript Isn';t多态性在jses中工作错误

Javascript Isn';t多态性在jses中工作错误,javascript,oop,polymorphism,ecma,Javascript,Oop,Polymorphism,Ecma,我目前正在开发一个浏览器扩展来管理打开的选项卡,我注意到在JSES中,当我在类的顶部声明类字段时,多态性的工作有点奇怪 假设我们希望在对象初始化中使用多态性 例如,我们有基类视图: 类视图{ _视图模型; 构造函数(视图模型){ 这是。_viewModel=viewModel; this.init(); } init(){} } 和派生类选项卡视图: 类选项卡视图扩展了视图{ _头衔; 构造函数(视图模型){ 超级(视图模型); } init(){ this.title=“测试”; } 获取标

我目前正在开发一个浏览器扩展来管理打开的选项卡,我注意到在JSES中,当我在类的顶部声明类字段时,多态性的工作有点奇怪

假设我们希望在对象初始化中使用多态性

例如,我们有基类视图:

类视图{
_视图模型;
构造函数(视图模型){
这是。_viewModel=viewModel;
this.init();
}
init(){}
}
和派生类选项卡视图:

类选项卡视图扩展了视图{
_头衔;
构造函数(视图模型){
超级(视图模型);
}
init(){
this.title=“测试”;
}
获取标题(){
返回此标题;
}
设置标题(值){
这个。_title=值;
}
}
现在,让我们尝试调用索引文件中的简单脚本来调试此示例

const选项卡视图=新选项卡视图(“模型”);
日志(tabView.title);
此示例的调用堆栈看起来正确(从上到下读取):

  • 选项卡式构造函数
  • 视图构造函数(由super()调用)
  • TabView init()(视图构造函数从TabView调用overwriten init方法)
选项卡视图的预期值

  • _viewModel:“模型”
  • _标题:“测试”
此选项卡视图的示例值为:

  • _viewModel:“模型”
  • _标题:“未定义”
当我调试这个示例时,它看起来像是从
视图调用
init()
方法,然后
这个
引用
视图
类,而不是
选项卡
。值保存在
视图
实例中,而
选项卡视图
字段仍为“未定义”。当我从
选项卡
类的顶部删除
\u title
字段时,一切都可以正常工作。最新版本的Firefox和Microsoft Edge的结果是一样的

我喜欢在顶部写类字段,所以我想问,这是JS ES的正确行为,还是一个可能在未来版本的ECMA脚本中得到纠正的错误

当我调试这个示例时,它看起来像是从
视图调用
init()
方法,然后
这个
引用
视图
类,而不是
选项卡
。值保存在
视图
实例中,
选项卡视图
字段仍然是
未定义的

请看下面的代码:

类视图{
_视图模型;
构造函数(视图模型){
这是。_viewModel=viewModel;
this.init();
}
init(){console.log(“View init”);}
}
类选项卡视图扩展了视图{
_头衔;
构造函数(视图模型){
超级(视图模型);
}
init(){
log(“TabView init”);
this.title=“测试”;
}
获取标题(){
日志(“获取标题”);
返回此标题;
}
设置标题(值){
控制台日志(“设置标题”);
这个。_title=值;
}
}
常量选项卡视图=新选项卡视图(“模型”);
日志(tabView.title)
当我调试这个示例时,它看起来像是从
视图调用
init()
方法,然后
这个
引用
视图
类,而不是
选项卡
。值保存在
视图
实例中,
选项卡视图
字段仍然是
未定义的

请看下面的代码:

类视图{
_视图模型;
构造函数(视图模型){
这是。_viewModel=viewModel;
this.init();
}
init(){console.log(“View init”);}
}
类选项卡视图扩展了视图{
_头衔;
构造函数(视图模型){
超级(视图模型);
}
init(){
log(“TabView init”);
this.title=“测试”;
}
获取标题(){
日志(“获取标题”);
返回此标题;
}
设置标题(值){
控制台日志(“设置标题”);
这个。_title=值;
}
}
常量选项卡视图=新选项卡视图(“模型”);

日志(tabView.title)好,这意味着JS ES按照规范的要求工作。我认为它的工作原理应该类似于编译语言,例如C#中的虚拟方法。我在等效的C#代码中测试了相同的解决方案,它的工作原理与我在JS中所认为的一样。在C#中,当您调用重写的方法时,
this
仍然引用派生类,但在JS中它引用调用派生方法的基类。所以JS并没有在派生类声明中初始化我的字段,而是在基类中创建一个新字段,该字段被我的“未定义”字段隐藏。谢谢你的回答,它解释了一切。不,那是不正确的。如果在JavaScript中有
类B扩展了A
,那么调用
new B()
永远不会引用
A
。为
this
创建一个新对象,然后将其传递给
A
的构造函数进行修改(例如,添加属性,完成实例化),但不是
A
(没有创建
A
的实例)。在构建过程结束时,您只有一个
B
对象,在这两者之间,您可能没有完全实例化
B
对象,但没有
a
。字段的规范只是要求它们
未定义
,如果在当前创建链中未初始化,这与实例无关。好的,这意味着JS ES在规范中应该起作用。我认为它的工作原理应该类似于编译语言,例如C#中的虚拟方法。我在等效的C#代码中测试了相同的解决方案,它的工作原理与我在JS中所认为的一样。在C#中,当您调用重写的方法时,
this
仍然引用派生类,但在JS中它引用调用派生方法的基类。所以JS并没有在派生类声明中初始化我的字段,而是在基类中创建一个新字段,该字段被我的“未定义”字段隐藏。谢谢