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

欢迎!请参阅关于页面了解更多有关如何使用本网站的信息。

+2
ClojureScript

支持生成 ES6 类

ES6 为 Javascript 引入了一种类语法。在最近版本之前,许多围绕这个功能的开发工作都是使用 polyfills 进行的,但随着浏览器的进步,越来越多的库开始原生地使用这个特性,这带来了一个问题。使用“修补”方法获取类时,您始终可以从子类中调用原始构造函数,但对于原生的 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")调用这个新构造函数会触发浏览器异常:未捕获 TypeError: 类构造函数 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

有些方法可以生成ES5构造函数,这些构造函数的行为类似于ES2015类,包括扩展。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报告)
...