Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/477.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 从非类继承ES6/TS类_Javascript_Typescript_Ecmascript 6 - Fatal编程技术网

Javascript 从非类继承ES6/TS类

Javascript 从非类继承ES6/TS类,javascript,typescript,ecmascript-6,Javascript,Typescript,Ecmascript 6,如果类是从非类(包括但不限于函数)扩展而来 后果是什么?规格上怎么说 看起来Babel、Google V8和Mozilla Spidermonkey的当前实现对此没有问题,TypeScript抛出了 类型“()=>void”不是构造函数类型 如果这是一个有效的ES2015代码,那么在TypeScript中处理它的正确方法是什么 后果是什么?规格上怎么说 这与扩展“EcmaScript 5”类相同。您的声明是一个构造函数,但根本没有原型。您可以毫无问题地扩展它 但是对于TypeScript,函数F

如果类是从非类(包括但不限于函数)扩展而来

后果是什么?规格上怎么说

看起来Babel、Google V8和Mozilla Spidermonkey的当前实现对此没有问题,TypeScript抛出了

类型“()=>void”不是构造函数类型

如果这是一个有效的ES2015代码,那么在TypeScript中处理它的正确方法是什么

后果是什么?规格上怎么说

这与扩展“EcmaScript 5”类相同。您的声明是一个构造函数,但根本没有原型。您可以毫无问题地扩展它

但是对于TypeScript,函数Fn(){}和类Fn{}之间有很大的区别。两者不是同一类型

第一个是一个不返回任何内容的函数(TypeScript用
()=>void
)显示它)。第二个是构造函数。TypeScript拒绝对非构造函数执行扩展

如果有一天javascript拒绝这样做,它将破坏许多javascript代码。因为目前,
函数Fn(){}
是用纯javascript声明类最常用的方法。但从TypeScript的角度来看,这不是“类型安全的”

我认为TypeScript的唯一方法是使用类:

class Fn {} 

class Class extends Fn {
    constructor() {
        super();
    }
}

我不确定是否回答了您的问题,但我对如何通过TypeScript类扩展JS函数非常感兴趣,因此我尝试了以下方法:

fn.js(注意扩展名
.js

c.ts

declare class Fn {}

class C extends Fn {
    constructor() {
        console.log("1");
        super();
        console.log("3");
    }
}

let c = new C();
c.sayHello();
然后我跑:

$ tsc --target es5 c.ts | cat fn.js c.js | node  # or es6
输出为:

1
2
3
Hello!
请注意,这不是用于生产的代码,而是在您没有时间将一些旧JS文件转换为TypeScript的情况下的一种变通方法

如果我处于OP状态,我会尝试将
Fn
转换为一个类,因为它使团队中的其他人更容易编写代码。

TypeScript部分 到目前为止,表示a
extends
claus后面必须跟一个TypeReference。a必须是
a.B.C
的形式,如
MyModule.MyContainer
。因此,从语法上讲,您的代码是正确的。但事实并非如此

规范规定
BaseClass
必须是有效的typescript类。然而,正如前面所说,规范已经过时了。现在,TypeScript允许extends子句中的表达式,只要表达式被计算为构造函数。定义是基于实现的。你可以看到。简单地说,如果一个表达式实现了
new(){}
接口,它就可以算作构造函数

ES2015部分 因此,您的问题是,在TypeScript中,普通函数未被识别为构造函数,这是有争议的,因为ES2015规范只要求对象具有
[[construct]]
内部方法。而用户定义的函数对象没有

运行时需要
基类
。如果对象具有
[[construct]]
,则它是构造函数。规范中说,
[[construct]]
是一种内部方法。用户函数是
函数对象的实例
,因此它们自然是构造函数。但是不能有
[[construct]]

例如,以下代码将抛出运行时
TypeError
,因为
parseInt
是一个内置函数,没有
[[construct]]

new parseInt()
// TypeError: parseInt is not a constructor
和来自ECMAScript

Arrow函数与内置函数类似,都缺少.prototype和任何[[Construct]]内部方法。因此new(()=>{})抛出一个TypeError,但在其他方面,箭头与函数类似:

根据经验,任何没有
原型的函数都不属于
新功能。

变通 简而言之,并不是每个函数都是构造函数,TypeScript通过要求
new(){}
来捕获这一点。然而,用户定义的函数是构造函数

interface FnType {}
var Fn: {new(): FnType} = (function() {}) as any

class B extends Fn {}
要解决这个问题,最简单的方法是将
Fn
声明为变量,并将其转换为构造函数

interface FnType {}
var Fn: {new(): FnType} = (function() {}) as any

class B extends Fn {}
推理不相容性 DISCALIMER:我不是一个TypeScript核心贡献者,只是一个TS迷,他有几个与TS相关的辅助项目。所以这一部分是我个人的猜测。

TypeScript是一个起源于ES2015的项目,当时ES2015还在昏暗的黑暗中隐约可见。TypeScript没有很好的类语义参考

当时,TypeScript的主要功能是与ES3/5保持兼容。因此,
new
ing函数在TypeScript中是合法的,因为它在ES3/5中也是合法的。同时,TypeScript还旨在捕获编程错误<代码>扩展
函数可能是一个错误,因为该函数可能不是一个合理的构造函数(例如,仅用于副作用的函数)<代码>扩展
在ES3/5中甚至不存在!因此,TypeScript可以自由定义自己对
extends
的用法,使得
extends
必须与
class
变量配对。这使得TypeScript更加类型安全,同时与JavaScript兼容

现在,ES2015规范已经定稿。JavaScript还有一个
extends
关键字!然后不相容性就来了。解决不兼容问题有很多方法。但问题依然存在<代码>()=>void或
函数
类型不应是可扩展的,如上所述,由于内置函数。以下代码将中断

var a: (x: string) => void = eval
new a('booom')
另一方面,如果在TypeScript中引入了
构造函数接口
,并且每个函数文本都实现了它,那么向后的不兼容性就会出现。下面的代码现在编译,但不是在引入
ConstructorInterface
时编译

var a = function (s) {}
a = parseInt // compile error because parseInt is not assignable to constructor

当然,TS团队可以有一个平衡这两个选项的解决方案。但这并不是一个高度优先事项。此外,如果完全实现了TS支持的JavaScript的代码名salsa。这个问题自然会解决。

这与
var a = function (s) {}
a = parseInt // compile error because parseInt is not assignable to constructor