Существуют ли проблемы с вызовом конструкторов 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
также непоследовательно применяется к конструкторам.