Можно ли вызвать функцию-конструктор через оператор new в JavaScript?
Что проверяют
Ответ «да» очевиден, поэтому интересно другое: знаете ли вы, какие функции через new вызвать нельзя и что именно делает оператор. Следом просят написать свою реализацию new или объяснить, что будет без него.
Как отвечать
Обычную функцию, объявленную через function, и класс через new вызвать можно. Что делает оператор:
- создание объекта: у нового объекта
[[Prototype]]указывает наF.prototype; - вызов функции: тело выполняется с
this, равным этому объекту; - возврат результата: возвращается созданный объект, если функция не вернула другой объект. Возврат примитива игнорируется, возврат объекта подменяет результат.
Конструктором быть не могут:
- стрелочные функции: у них нет своего
thisиprototype,newбросаетTypeError: ... is not a constructor; - методы и особые функции: методы в сокращённой записи
{ m() {} },asyncфункции и генераторы; - многие встроенные функции:
Math.max,Symbol,BigInt. СDateдругая история:Date()безnewвернёт строку, а не объект.
Обратная ситуация: класс без new вызвать нельзя, будет TypeError: Class constructor X cannot be invoked without 'new'. Внутри обычной функции способ вызова проверяют через new.target: он равен undefined, если new не было.
Во фронтенде функции-конструкторы сейчас почти не пишут вручную, используют class. Но механику знать нужно: на ней держатся прототипное наследование, instanceof и код старых библиотек, который до сих пор встречается в проектах.
Где спотыкаются
Пишут конструктор стрелочной функцией, например в свойстве объекта, и получают TypeError при первом же new.
Вызывают функцию-конструктор без new. В нестрогом режиме this становится глобальным объектом, и свойства молча утекают в window. В строгом режиме и в модулях this равен undefined, и падает первое присваивание.
Кладут методы внутрь конструктора через this.method = function () {}. Каждый экземпляр получает собственную копию функции, хотя место ей в prototype или в теле класса.