2024 Clojure状态调查!中分享您的看法。

欢迎!请参阅关于页面以获取有关如何工作的更多详细信息。

+2
ClojureScript

支持生成ES6类

ES6为JavaScript引入了类语法。在Recent版本之前,与此有关的许多工作都使用polyfills,但随着浏览器的发展,越来越多的库开始直接使用这个功能,这带来了一个问题。使用获取类的方法“hacked”,你始终可以从子类中调用原始构造函数,这对于原生的ES6类来说不是真的。为了演示这个问题,让我们看看一个在JS中的简单类扩展情况:

`
class A {
constructor(x) {

this.x = x;

}
}

class B extends A {
constructor(foo) {

super(foo);

}
}
`

尝试不使用类来复制此操作的代码如下:

`
function B(foo) {
A.prototype.constructor.call(this, foo);
}

Reflect.setPrototypeOf(B.prototype, A.prototype)
`

但尝试使用new B("bar")调用这个新构造函数会触发浏览器的异常: 未捕获的类型错误:类构造函数A在没有'new'的情况下无法调用

根本问题是构造函数不能作为函数调用,这限制了ClojureScript的范围,因为它阻止了直接扩展这些类的能力,而不得不回退到常规JS来处理这些情况。

所以这似乎需要某些方法从Clojurescript生成实际的ES6类(可能是一个defclass宏?)。

本探索中使用的一些资源

https://rete.js.org - 使用原生类并依靠它进行其使用的库
https://esdiscuss.org/topic/extending-an-es6-class-using-es5-syntax - 关于使用ES5模拟ES6类的讨论
https://medium.com/@robertgrosse/how-es6-classes-really-work-and-how-to-build-your-own-fd6085eb326a - 更多有关如何类的文档

但所有这些资源似乎都处理的是一个原生类还不存在的时候,所以它们不需要处理原生的构造函数调用。

3个答案

0

评论者:dnolen

我们可能需要一个设计页面来列出此工单的选项和权衡。这个工单将在完成此操作之前不会进行。

0

评论者:filipematossilva

有一些方法可以生成行为如同ES2015类的ES5构造函数,包括扩展。TypeScript就是一个很好的例子。

原始代码

`
class A {
constructor(x) {

this.x = x;

}
}

class B extends A {
constructor(foo) {

super(foo);

}
}

const b = new B("bar")
`

转换成

`
var extends = (this && this.extends) || (function () {

var extendStatics = function (d, b) {
    extendStatics = Object.setPrototypeOf ||
        ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
        function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
    return extendStatics(d, b);
};
return function (d, b) {
    extendStatics(d, b);
    function __() { this.constructor = d; }
    d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
};

})();
var A = /* @class / (function () {

function A(x) {
    this.x = x;
}
return A;

}());
var B = /* @class / (function (_super) {

__extends(B, _super);
function B(foo) {
    return _super.call(this, foo) || this;
}
return B;

}(A));
var b = new B("bar");
`

其中{{__extends}}是由TS生成的助手,可以是内联的,也可以从名为{{tslib}}的帮助库中导入。

因此,似乎没有必要从CLJS内部制作ES2015类。

0
参考资料:https://clojure.atlassian.net/browse/CLJS-3084 (由 wilkerlucio 报告)
...