Illegal constructor что это значит
Перейти к содержимому

Illegal constructor что это значит

  • автор:

Unexpected `Uncaught TypeError: Illegal constructor` when creating a new vanilla Web Component

I’m testing the limits of the JavaScript Web Components API and I encountered an interesting issue. I have the following wrapper around an HTMLElement object:

export class Wrapper < public el: HTMLElement; constructor(elementName: string) < this.el = document.createElement(elementName); customElements.get(elementName) || customElements.define(elementName, HTMLElement); >> 

I use this implementation because HTMLElement has a series of limitations I want to bypass, e.g. the constructor must be empty. Then, I instanciate the wrapper and append the actual element to the DOM:

let wrapper = new Wrapper("magic-component") document.body.appendChild(wrapper.el); 

To my surprise, this throws the following error:

Uncaught TypeError: Illegal constructor

It appears this error happens when a custom element is created via new before being defined via customElements.define() . However, this is not the case here: this.el is regularly created via document.createElement() and then defined via customElements.define() . Only the wrapper is created via new .

class Wrapper < constructor(elementName) < this.el = document.createElement(elementName); customElements.get(elementName) || customElements.define(elementName, HTMLElement); >> let wrapper = new Wrapper("magic-component") document.body.appendChild(wrapper.el);

Возможно ли унаследоваться, например, от HTMLDivElement стандартным способом и создавать элементы через конструктор?

Про document.registerElement я осведомлен, но наследование там неудобное и спецификация только draft
А влоб унаследоваться от HTMLElement я так подозреваю невозможно сейчас? Выходит, без полного определения своего элемента со своим уникальным тегом создать расширенный элемент на базе существующего не удастся? Т.е , расширенный элемент с тем же тегом, но который можно создать только из js т.е парсер html браузера не должен спаунить его. Что то нечеловеческие api делают эти разработчики спецификации. Хотелось бы наследоваться как от обычного объекта js, а они палки в колеса ставят. грусть-печалька. =(

try < var nativeDiv = new HTMLDivElement(); //Uncaught TypeError: Illegal constructor console.log(nativeDiv); document.body.appendChild(nativeDiv); >catch(err) < console.error(err); >var inherit= function (context, Parent) < if (typeof Parent!=='function') throw new TypeError('given supper class is not constructor!'); var F = function () <>; F.prototype = Parent.prototype; context.prototype = new F(); context.prototype.constructor = context; context.base = Parent.prototype; return context; > function WidgetElement()<> inherit(WidgetElement,HTMLDivElement); WidgetElement.prototype.burnTheWorld=function(); var custom=new WidgetElement(); document.body.appendChild(custom); //Uncaught TypeError: Failed to execute 'appendChild' on 'Node': parameter 1 is not of type 'Node'.
  • Вопрос задан более трёх лет назад
  • 680 просмотров

Комментировать
Решения вопроса 1
Open Source enthusiast

и спецификация только draft

Есть полифиллы для достаточно качественной поддержки.

Что то нечеловеческие api делают эти разработчики спецификации. Хотелось бы наследоваться как от обычного объекта js, а они палки в колеса ставят. грусть-печалька. =(

Я присылал исправления в полифиллы, которые поддерживают разработчики из Google, так вот, там столько нюансов возникает при наследовании, что я бы на вашем месте был поосторожнее с такими высказываниями)

В целом — создавайте свой тэг с помощью WebComponents.js, IE10+ работает ОК, использую постоянно уже достаточно давно, по началу были баги, приходилось самому исправлять и отправлять патчи, сейчас всё достаточно стабильно и хорошо кроме случаев когда полифилл в принципе не может обеспечить имитацию функциональности (описано у них в документации, не критично на самом деле).

Ответ написан более трёх лет назад
Нравится 2 4 комментария

DIITHiTech

Dmitriy Mozgovoy @DIITHiTech Автор вопроса

Полифилы спасут от слегка устаревших браузеров, а от изменения API разработчиками никак не спасают. Если измениться API- либо переписывать свой код, либо искать костыль имитации старого API и таскать за собой, чего очень хочется избежать=)
Нюансы возникают, из того что новый костыль исправляет недочеты предыдущего костыля.
Полифилы то совсем другое дело, они имитируют на уровне кода, они ограничены возможностями среды. Но кто мешал разработчикам на уровне движка перед выпуском html5 выпустить новую версию DOM, и дать выбирать режим совместимости со скрипта на переходное время? Хотя не пойму что им там так мешает сделать прозрачное прототипное наследование, все таки html5 выходит по большей части.
ИМХО приятнее было бы писать как и с обычными объектами, чтоб легко переделывать старые кодинги:

WidgetElement=function()< WidgetElement.base.constructor.apply(this,arguments); >; inherit(WidgetElement, HTMLDivElement); WidgetElement.prototype.extend( < listenTo:function()<>. >) ClockWidget=function()< ClockWidget.base.constructor.apply(this,arguments); >; inherit(ClockWidget, WidgetElement); var widget=new WidgetElement(); document.registerElement("clock-widget", ClockWidget); //если надо - зарегили, не надо- то с html не создать

Что ж.. пока придется по старой школе — обертка над элементом + MutationObserver =\

Дмитрий: Если бы так сделали — выход HTML5 в текущем виде задержался бы ещё на пару лет. В общем ваш вариант будет самым быстрым, так как полифиллы под капотом используют тот же MutationObserver. Посмотрите на Polymer, особенно версию 0.8-0.9 — они как раз и есть простыми обертками над браузерными фичами, и сглаживают несовместимости, интерфейс подобно тому, который вы желаете получить там есть.

DIITHiTech

Dmitriy Mozgovoy @DIITHiTech Автор вопроса

Назар Мокринский: в html5 куча всяких плюшек, которые очень редкие в использовании, в ES6 втулили много того что и так как бы есть, особенно кофейникам, но вот исправить этот старый камень преткновения не рискнули=) будем надеяться- что MutationObserver действительно стал настолько производительнее как говорят. Polymer, наверно, отпадает (много плюшек), скорее чистый полифил document-register-element, хотел просто проапгрейтить свой слегка старый код по работе с визуальными компонентами , надеялся что поправлю и унаследую там от HTMLElement вместо Object и тонну кода обертки можно будет вкинуть, но пока не судьба=)

Дмитрий: Как раз не много плюшек, он стал в версии 0.8-0.9 (ветка 0.8-preview в репозитории, файл PRIMER.md) очень модульным, ядро совсем маленькое, а дальше что нужно — то и выбираете, вот реально посмотрите на него, так же они далеко продвинулись в плане производительности, но ещё не все фичи из 0.5 перенесли, да и не все перенесут в итоге (часто из-за производительности).

How to solve «Uncaught TypeError: Illegal constructor»

This is a quite common error, frequently appearing for people building or using Custom Elements and Web Components.

Let’s take this class as an example:

export default class LoadingIndicator extends HTMLElement  constructor()  super(); > > new LoadingIndicator(); // Uncaught TypeError: Illegal constructor 

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.define("loading-indicator", LoadingIndicator); 

Then you use it as a custom element:

loading-indicator>loading-indicator> 

TypeError: «x» is not a constructor

Была попытка использовать объект или переменную как конструктор, однако этот объект или переменная — не конструктор. Смотрите constructor или new operator, чтобы получить больше информации о том, что такое конструктор.

Существует множество глобальных объектов, таких как String или Array , которые можно построить с использованием new . Однако, некоторые глобальные объекты — нельзя, т.к. их свойства и методы статичны. Следующие стандартные встроенные объекты JavaScript — не конструкторы: Math , JSON , Symbol , Reflect , Intl , SIMD , Atomics .

Функции-генераторы также не могут быть использованы как конструкторы.

Примеры

Неправильное использование

var Car = 1; new Car(); // TypeError: Car is not a constructor new Math(); // TypeError: Math is not a constructor new Symbol(); // TypeError: Symbol is not a constructor function* f() > var obj = new f(); // TypeError: f is not a constructor 

Конструктор «car» (автомобиль)

Представьте, что вы хотите создать тип объекта для автомобилей. Вы хотите, чтобы этот тип объектов назывался car , и вы хотите, чтобы были свойства для производителя, модели и года выпуска. Чтобы сделать это, вы должны написать следующую функцию:

function Car(make, model, year)  this.make = make; this.model = model; this.year = year; > 

Теперь вы можете создать объект, который называется mycar (мой автомобиль) следующим образом:

var mycar = new Car("Лада", "Самара", 1993); 

В Промисах

В случае, когда возвращается незамедлительно разрешённый или незамедлительно отклонённый промис, вам не нужно создавать новый промис new Promise(. ) и работать с ним.

Это неправильно (конструктор Promise вызывается неправильно) и будет вызывать исключение TypeError: this is not a constructor :

return new Promise.resolve(true); 
// Это допустимо, но слишком длинно, в этом нет необходимости: return new Promise((resolve, reject) =>  resolve(true); >); // Вместо этого, возвращайте статический метод: return Promise.resolve(true); return Promise.reject(false); 

Смотрите также

Found a content problem with this page?

  • Edit the page on GitHub.
  • Report the content issue.
  • View the source on GitHub.

This page was last modified on 7 авг. 2023 г. by MDN contributors.

Your blueprint for a better internet.

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *