Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Illegal constructor with EcmaScript 6

First of all I would like that say that I don't really know how I can explain what I did on order to get the error mentioned in the title (uncaught TypeError: Illegal constructor). I am using gulpfile in order to compile my Ecmascript 6 to plain Javascript. My gulpfile looks like this:

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);
}

I have a filesystem where all files are concatenated to one file (bundle.js), after being compiled with Babel.

In the browsers console (either Chrome or Firefox), the error appears and it is located in the next line:

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

The error within the console

This is the non-compiled code of this:

class Dropdown extends Node {

    constructor(element) {
        super(element);

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

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

And this is the compiled code of the same class:

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);

I am not using export default Dropdown because I am not importing modules in other modules (this is not needed because every file is converted to one file, where everything is accessible).

I did some research and the only reason why peoeple got this error was because there was a capital letter where none was allowed. I didn't find anything else about the cause of this error. Does someone have an idea why I get this error? And does someone have a solution?

like image 594
Eran Machiels Avatar asked Jan 07 '17 13:01

Eran Machiels


People also ask

What does illegal constructor mean?

The Illegal constructor error is thrown when a class extends HTMLElement, but is instantiated like a regular class. Using classes that inherits from HTMLElement requires you to define them as custom elements to initialize them, like this: customElements.

What is Illegal invocation JavaScript?

An "illegal invocation" error is thrown when calling a function whose this keyword doesn't refer to the object where it originally did. In other words, the original "context" of the function is lost.


2 Answers

This is the first Google result for this error message and it also frequently comes up in conjunction with web components. With a perfectly valid looking web component like this:

export default class UserAvatar extends HTMLElement {
  constructor() {
    super();
  }
}

You will get this error if you forget to call customElements.define and try to instantiate the component.

So, new UserAvatar will fail with Illegal constructor. To fix it, define it first:

customElements.define('tom-user-avatar', UserAvatar);

It's a bad error message in both Firefox and Chrome, the browser vendors should do a better job here. If you're using document.createElement instead of new UserAvatar you will likely catch this quickly though, because it will remind you that you haven't set up the name. There are reasons for initiating custom elements with a constructor though, like passing in initialization parameters.

like image 63
Tomáš Hübelbauer Avatar answered Sep 27 '22 17:09

Tomáš Hübelbauer


It looks like you're trying to extend DOM's Node. You can't do that, it's defined as an abstract interface, and the host-provided function exposed in browsers for it can't be called as a constructor (even by subclasses).

like image 30
T.J. Crowder Avatar answered Sep 27 '22 17:09

T.J. Crowder