Существуют ли проблемы с вызовом конструкторов JavaScript в качестве функций (без новых?)

Недавно у меня появилась привычка вызывать такие вещи, как RegExp, String, Number, Object, TypeError и т.д. без "новых".

например:

throw (TypeError("Error"));
var regex = RegExp('^word$');

Я знаю, что это плохо для случаев, когда нужен контекст "this", так как без "нового", "this" может привести к хаосу в вашей глобальной области действия, если вы не закроете свой код в "use strict", и в этом случае он поднимает ошибка, которую вы пытаетесь изменить "undefined". (Я не уверен, что это работает в очень старых браузерах).

например:

var constructor = function() {
    // 'use strict'; /* uncomment this line to avoid the behavior and be warned */
    this.state = 'working as intended';
};

var foo = constructor();
console.log(foo.state); // undefined
console.log(window.state); // we just polluted our global scope.

тогда как

var constructor = function() {
    this.state = 'working as intended';
};

var foo = new constructor;
console.log(foo.state); // "working as intended"
console.log(window.state); // we are clean.

Но в таких случаях, как выше, это нормально делать, или есть проблемы, которые я настраиваю, если у меня есть привычка делать это?

Спасибо заранее.

Ответ 1

Знайте, что результат может быть другим.

Например, конструктор Number создает объекты Number, но при вызове как функции он только вводит принуждение к примитивному номеру.

new Number(123); // Number { 123 }
Number(123); // 123

Но да, есть много случаев, в которых не имеет значения, используете ли вы new или нет. Они существуют из-за обратной совместимости, но с недавно введенными конструкторами, такими как Set или Map, требуется new.

В общем, я бы рекомендовал использовать new, если вы хотите создать новый объект. Тогда,

  • Если вы хотите использовать принуждение типа, вы должны вызвать Boolean, Number или String без new.
  • По той же причине, если вы хотите принуждение к типу Object, я бы не использовал new, но это не имеет значения.
  • Если вы хотите создать примитив, который не имеет буквенного синтаксиса, вы должны вызвать Symbol без new.
  • Если вы хотите создать обертку объекта примитивного значения, вы должны вызвать Boolean, Number, String или Symbol с помощью new.
  • Если вы хотите создать экземпляр старого конструктора типа Array, Object, RegExp, Error и т.д., я бы использовал new, но это не имеет значения.
  • Если вы хотите создать экземпляр недавно введенного конструктора типа Set, Map, WeakSet, WeakMap, типизированных массивов и т.д., вы должны называть его new.

Для старых конструкторов это не имеет значения, как будто они называют себя new, если вы его опустите. Например, для RegExp,

Когда RegExp вызывается как функция, а не как конструктор, создает и инициализирует новый объект RegExp. Таким образом, вызов функции RegExp(…) эквивалентно выражению создания объекта new RegExp(…) с теми же аргументами.

Ответ 2

Как указано в другом ответе, некоторые встроенные конструкторы записываются так, чтобы быть вызванными как функции. Поэтому, пока вы не загрязняете свое глобальное пространство имен, я считаю, что вы должны быть в порядке с приведенным вами примером.

В большинстве случаев я не привык к этой привычке; оператор new добавляет к ясности кода, что более важно, чем краткость. Возможность использования встроенных конструкторов без оператора new также непоследовательно применяется к конструкторам.