EcmaScript 6中的非法构造函数

14

首先,我想说我不是很清楚如何解释我所做的事情以导致标题中提到的错误(uncaught TypeError: Illegal constructor)。我正在使用gulpfile将我的Ecmascript 6编译成普通的Javascript。我的gulpfile看起来像这样:

var gulp = require('gulp');
var concat = require('gulp-concat');
var babel = require('gulp-babel');

gulp.task('compile', function () {
    return gulp.src(['resources/assets/js/*.js', 'resources/assets/js/components/*.js'])
        .pipe(babel({
                presets: ['es2015']
        }).on('error', logError))
        .pipe(concat('bundle.js'))
        .pipe(gulp.dest('public/js'));
});

gulp.task('watch', function () {
   gulp.watch('resources/assets/js/**/*', ['compile']);
})

gulp.task('default', ['watch']);

function logError(err) {
    console.log(err);
}

我的文件系统将所有文件合并到一个文件(bundle.js)中,在使用Babel编译后。

在浏览器控制台(Chrome或Firefox),下一行出现错误:

var _this = _possibleConstructorReturn(this, (Dropdown.__proto__ || Object.getPrototypeOf(Dropdown)).call(this, element));

控制台中的错误

这是此代码的非编译版本:

class Dropdown extends Node {

    constructor(element) {
        super(element);

        this.registerEvents(['click', 'change', 'blur']);
    }

    onClick() {
        this.$element.addClass('clicked');
    }
}

这是相同类的编译代码:

var Dropdown = function (_Node) {
    _inherits(Dropdown, _Node);

    function Dropdown(element) {
        _classCallCheck(this, Dropdown);

        var _this = _possibleConstructorReturn(this, (Dropdown.__proto__ || Object.getPrototypeOf(Dropdown)).call(this, element));

        _this.registerEvents(['click', 'change', 'blur']);

        return _this;
    }

    _createClass(Dropdown, [{
        key: 'onClick',
        value: function onClick() {
            this.$element.addClass('clicked');
        }
    }]);

    return Dropdown;
}(Node);

我没有使用export default Dropdown,因为我不在其他模块中导入模块(这是不必要的,因为每个文件都转换为一个文件,在其中一切都可以访问)。

我做了一些研究,唯一的原因是,因为有一个大写字母不允许出现的地方,所以才会出现这个错误。我没找到其他关于这个错误的原因。有人知道我为什么会出现这个错误吗?有人有解决方法吗?


什么是 Node?如果它是 DOM 的 Node,你不能在 JavaScript 中扩展它。 - T.J. Crowder
如果您无法实例化Node(而且确实如此),那么您显然也无法实例化子类。 - Estus Flask
你需要导入需要扩展的文件吗?如果要扩展的类在同一个文件中定义(没有 export default superClass),那么这样做是否可行? - Eran Machiels
@Galago:如果在同一个文件中定义,那就完全没问题。 - T.J. Crowder
2个回答

56

这是该错误信息的第一个谷歌搜索结果,并且经常与Web组件一起使用。像这样具有完全有效外观的Web组件:

export default class UserAvatar extends HTMLElement {
  constructor() {
    super();
  }
}
如果忘记调用customElements.define并尝试实例化组件,您将会收到此错误。所以new UserAvatar会失败,显示非法构造函数。要修复这个问题,首先需要定义它:customElements.define('tom-user-avatar', UserAvatar); 无论在Firefox还是Chrome中,这都是一个糟糕的错误信息,浏览器厂商应该在这方面做得更好。如果您使用的是document.createElement而不是new UserAvatar,那么您很可能会很快发现这个问题,因为它会提醒您还没有设置名称。然而,使用构造函数初始化自定义元素有其原因,例如传递初始化参数。

1
绝对惊人的回应,谢谢! - Luillyfe
1
这就是我遇到的问题。非常感谢! - abhishek89m
2
我在使用Web组件时遇到了相同的错误,但只有在Safari上(而不是Firefox)出现。原因是我使用了class UserAvatar extends HTMLSpanElement(而不是HTMLElement)。 - Claude
但是,如果我不想创建一个 Web 组件呢? - Michael
那么,您可能正在寻找该问题的另一个答案或遇到尚未涵盖在这两个答案中的问题,此时您应该发布一个带有所有相关细节的新问题。 - Tomáš Hübelbauer
1
我不知道为什么这不是被接受的答案...感谢你的帮助... - Walid Ammar

14

看起来你正在尝试扩展DOM的Node。你不能这样做,因为它被定义为一个抽象接口,而在浏览器中为其公开的主机提供的函数不能作为构造函数调用(即使是子类也不行)。


1
谢谢,我忘记添加 import { Node } from 'tiptap',所以它使用了全局的 Node 定义。 - kelunik

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接