Крокфорд много сделал для популяризации хороших методов JavaScript. Его самоуверенная позиция по ключевым элементам языка вызвала много полезных дискуссий. Тем не менее, есть слишком много людей, которые воспринимают каждое провозглашение «плохого» или «вредного» как Евангелие, отказываясь выходить за пределы мнения одного человека. Это может быть немного расстраивающим время от времени.
Использование функциональности, предоставляемой new
ключевым словом, имеет несколько преимуществ по сравнению с созданием каждого объекта с нуля:
- Наследование прототипа . Несмотря на то, что те, кто привык к ОО-языкам на основе классов, часто воспринимаются со смесью подозрений и насмешек, родная технология наследования JavaScript является простым и удивительно эффективным средством повторного использования кода. И новое ключевое слово является каноническим (и только доступным кроссплатформенным) средством его использования.
- Представление. Это побочный эффект # 1: если я хочу добавить 10 методов к каждому объекту, который я создаю, я мог бы просто написать функцию создания, которая вручную назначает каждый метод каждому новому объекту ... Или я мог бы назначить их создание функций
prototype
и использование new
для удаления новых объектов. Это не только быстрее (код не требуется для каждого метода в прототипе), но и позволяет избежать раздувания каждого объекта с отдельными свойствами для каждого метода. На медленных машинах (или особенно медленных JS-интерпретаторах), когда создается много объектов, это может означать значительную экономию времени и памяти.
И да, new
имеет один существенный недостаток, умело описанный другими ответами: если вы забудете его использовать, ваш код сломается без предупреждения. К счастью, этот недостаток легко устранить - просто добавьте немного кода в саму функцию:
function foo()
{
// if user accidentally omits the new keyword, this will
// silently correct the problem...
if ( !(this instanceof foo) )
return new foo();
// constructor logic follows...
}
Теперь вы можете иметь преимущества, new
не беспокоясь о проблемах, вызванных случайным неправильным использованием. Вы могли бы даже добавить утверждение к проверке, если мысль о неработающем коде, молча работающем, беспокоит вас. Или, как некоторые прокомментировали, используйте проверку, чтобы ввести исключение времени выполнения:
if ( !(this instanceof arguments.callee) )
throw new Error("Constructor called as a function");
(Обратите внимание, что этот фрагмент позволяет избежать жесткого кодирования имени функции конструктора, так как в отличие от предыдущего примера он не нуждается в создании экземпляра объекта - следовательно, он может быть скопирован в каждую целевую функцию без изменения.)
Джон Резиг подробно описывает эту технику в своем посте «Простое создание класса» , а также о том, как по умолчанию включить это поведение в ваши «классы». Определенно стоит читать ... как его предстоящая книга Секреты JavaScript Ninja , который находит скрытые золота в этом и многих других «вредных» особенности языка JavaScript ( раздел на with
специально просветить для тех из нас , кто первоначально отклонил это очень клеветническая особенность как уловка).