JavaScript: использование конструктора без оператора 'new' - PullRequest
27 голосов
/ 18 декабря 2009

Пожалуйста, помогите мне понять, почему работает следующий код:

<script>
    var re = RegExp('\\ba\\b') ;
    alert(re.test('a')) ;
    alert(re.test('ab')) ;
</script>

В первой строке нет оператора new.

Насколько я знаю, конструктор в JavaScript - это функция, которая инициализирует объекты, созданные оператором new, и они не должны ничего возвращать.

Ответы [ 2 ]

36 голосов
/ 18 декабря 2009

В общем, если что-то задокументировано как конструктор, используйте new с ним. Но в этом случае RegExp имеет определенное «фабричное» поведение для ситуации, когда вы вызываете его как функцию. См. Раздел 15.10.3 скрипта ECMAScript (JavaScript) (который ссылается на исходящую спецификацию; номер раздела такой же, как и в новой спецификации, которую можно загрузить с главной страницы ECMA *) 1006 * [с правой стороны]; я не хочу напрямую ссылаться на файл PDF ~ 4 МБ):

15.10.3. Конструктор RegExp, вызываемый как функция
15.10.3.1 RegExp (шаблон, флаги)
Если pattern - это объект R, у которого свойство [[Class]] равно "RegExp" и флаги не определены, то вернуть R без изменений. В противном случае вызовите конструктор RegExp (15.10.4.1), передав ему аргументы pattern и flags, и верните объект, созданный этим конструктором.

На самом деле вы можете определить свои собственные функции конструктора JavaScript, чтобы позволить опускать ключевое слово new (обнаруживая, что они были вызваны как функции, а также поворачиваясь и вызывая себя правильно), но я бы не предложил это как это приводит к вводящему в заблуждение коду.

10 голосов
/ 18 декабря 2009

+ 1 TJ Crowder имеет это.Стандарт ECMAScript делает все возможное, чтобы определить поведение встроенных функций конструктора при вызове в виде простых функций.Часто он просто вызывает себя обратно как конструктор, но есть и более сложные случаи.

конструкторы в javascript [...] не предназначены для возврата чего-либо

В общем случае конструктор может игнорировать this и просто возвращать независимый объект:

function Thing() {
    return {'foo': 1};
}

, в этом случае вы можете в равной степени использовать функцию в качестве конструктора (с new)или простая функция.

Если конструктор ничего не возвращает, как это обычно делается для конструкторов, сам оператор new гарантирует, что он возвращает новый объект, созданный и переданный как this.В этом случае вы должны использовать new.

Лучше не полагаться на конструктор, работающий как голая функция, и альтернативные варианты поведения встроенных конструкторов редко используются, поэтому обычно вам следуетпридерживаться new.

...