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