В другом вопросе пользователь указал, что new
ключевое слово опасно для использования, и предложил решение для создания объекта, которое не использовалось new
. Я не верил, что это правда, в основном потому, что я использовал Prototype, Scriptaculous и другие прекрасные библиотеки JavaScript, и все использовали new
ключевое слово.
Несмотря на это, вчера я смотрел выступление Дугласа Крокфорда в театре YUI, и он сказал то же самое, что он больше не использовал new
ключевое слово в своем коде ( Крокфорд на JavaScript - Акт III: Функция Предельного - 50:23 минут ).
Это «плохо» использовать new
ключевое слово? Каковы преимущества и недостатки его использования?
javascript
Пабло Фернандес
источник
источник
new
. Но когда вы смотрите на библиотеку YUI. Вы должны использоватьnew
везде. Такие какvar myDataSource = new Y.DataSource.IO({source:"./myScript.php"});
.init
метод, если вы используетеObject.create
подход, и вызвать его после. Гораздо проще просто использовать,new
который выполняет обе функции, устанавливает цепочку прототипов и вызывает некоторый код инициализатора.new
не опасно. Пропускатьnew
опасно, а значит и плохо . Но в ES5 вы можете использовать строгий режим , который защищает вас от этой опасности и многие другие.Ответы:
Крокфорд много сделал для популяризации хороших методов JavaScript. Его самоуверенная позиция по ключевым элементам языка вызвала много полезных дискуссий. Тем не менее, есть слишком много людей, которые воспринимают каждое провозглашение «плохого» или «вредного» как Евангелие, отказываясь выходить за пределы мнения одного человека. Это может быть немного расстраивающим время от времени.
Использование функциональности, предоставляемой
new
ключевым словом, имеет несколько преимуществ по сравнению с созданием каждого объекта с нуля:prototype
и использованиеnew
для удаления новых объектов. Это не только быстрее (код не требуется для каждого метода в прототипе), но и позволяет избежать раздувания каждого объекта с отдельными свойствами для каждого метода. На медленных машинах (или особенно медленных JS-интерпретаторах), когда создается много объектов, это может означать значительную экономию времени и памяти.И да,
new
имеет один существенный недостаток, умело описанный другими ответами: если вы забудете его использовать, ваш код сломается без предупреждения. К счастью, этот недостаток легко устранить - просто добавьте немного кода в саму функцию:Теперь вы можете иметь преимущества,
new
не беспокоясь о проблемах, вызванных случайным неправильным использованием. Вы могли бы даже добавить утверждение к проверке, если мысль о неработающем коде, молча работающем, беспокоит вас. Или, как некоторые прокомментировали, используйте проверку, чтобы ввести исключение времени выполнения:(Обратите внимание, что этот фрагмент позволяет избежать жесткого кодирования имени функции конструктора, так как в отличие от предыдущего примера он не нуждается в создании экземпляра объекта - следовательно, он может быть скопирован в каждую целевую функцию без изменения.)
Джон Резиг подробно описывает эту технику в своем посте «Простое создание класса» , а также о том, как по умолчанию включить это поведение в ваши «классы». Определенно стоит читать ... как его предстоящая книга Секреты JavaScript Ninja , который находит скрытые золота в этом и многих других «вредных» особенности языка JavaScript ( раздел на
with
специально просветить для тех из нас , кто первоначально отклонил это очень клеветническая особенность как уловка).источник
new
, либо используйте функцию-обертку, чтобы запомнить ее для себя. Я подозреваю, что если вы находитесь в точке, где это имеет значение, вы уже исчерпали другие оптимизации, такие как запоминание, так что ваши вызовы создания будут в любом случае локализованы ...arguments.callee
для проверки того, что вам звонили,new
может быть не очень хорошим, посколькуarguments.callee
недоступно в строгом режиме. Лучше использовать имя функции.new
потому что вы можете забыть написать это в своем коде, так же смешно, как мой пример.Я только что прочитал некоторые части его книги Крокфордса "Javascript: The Good Parts". У меня такое ощущение, что он считает все, что когда-либо укусило его, вредным:
О переключателе провалиться:
О ++ и -
О новом:
Есть еще, но я надеюсь, что вы получите картину.
Мой ответ на ваш вопрос: нет, это не вредно. но если вы забудете использовать его, когда у вас возникнут проблемы, у вас могут возникнуть проблемы. Если вы развиваетесь в хорошей среде, вы это замечаете.
Обновить
Примерно через год после написания этого ответа была выпущена пятая редакция ECMAScript с поддержкой строгого режима . В строгом режиме
this
больше не привязан к глобальному объекту, а кundefined
.источник
Javascript - это динамический язык, и существует множество способов запутаться, когда другой язык остановит вас.
Избегать фундаментальной языковой особенности, например,
new
из-за того, что вы можете испортить это, все равно что снимать свои блестящие новые туфли перед тем, как идти по минному полю, на случай, если вы можете испачкать свои туфли.Я использую соглашение, в котором имена функций начинаются со строчной буквы, а «функции», которые на самом деле являются определениями классов, начинаются с заглавной буквы. Результатом является действительно весьма убедительный визуальный признак того, что «синтаксис» неверен:
Вдобавок к этому хорошие привычки именования помогают. В конце концов, все функции делают что-то, и поэтому в его имени должен быть глагол, тогда как классы представляют объекты и являются существительными и прилагательными без глагола.
Интересно, как раскраска синтаксиса SO интерпретировала код выше.
источник
if (! this instanceof MyClass) return new MyClass()
) я фактически предпочитаюnew
синтаксис -less. Почему? Потому что функции являются более общими, чем функции конструктора . Отсутствиеnew
упрощает преобразование функции конструктора в обычную функцию ... Или наоборот. Добавление вnew
делает код более конкретным, чем он должен быть. И, следовательно, менее гибким. Сравните с Java, где рекомендуется приниматьList
вместо того,ArrayList
чтобы вызывающий мог выбрать реализацию.Я новичок в Javascript, так что, возможно, я не слишком опытен в предоставлении хорошей точки зрения на это. И все же я хочу поделиться своим взглядом на эту «новую» вещь.
Я пришел из мира C #, где использование ключевого слова «new» настолько естественно, что мне кажется странным, что это шаблон фабричного дизайна.
Когда я впервые пишу код в Javascript, я не понимаю, что есть «новое» ключевое слово и код, подобный коду в шаблоне YUI, и мне не понадобится много времени, чтобы столкнуться с катастрофой. Я теряю представление о том, что должна делать конкретная строка при просмотре кода, который я написал. Более хаотичным является то, что мой разум не может действительно переходить между границами экземпляров объектов, когда я «пробую» код.
Затем я нашел «новое» ключевое слово, которое для меня это «отдельные» вещи. С новым ключевым словом он создает вещи. Без нового ключевого слова, я знаю, я не буду путать его с созданием вещей, если функция, которую я вызываю, не дает мне ясного представления об этом.
Например, у
var bar=foo();
меня нет никаких подсказок о том, какой бар может быть ... Это возвращаемое значение или это вновь созданный объект? Ноvar bar = new foo();
я точно знаю, что бар - это объект.источник
typeof new foo() == "object"
. Это то, чтоnew
возвращает экземплярfoo
, и вы знаете, что можете позвонитьfoo.bar()
иfoo.bang()
. Однако это можно легко исправить с помощью @turn JsDoc. Не то, чтобы я выступал за процедурный кодекс (избегая словаnew
)Другой случай для нового - это то, что я называю Pooh Coding . Винни-Пух следует за своим животиком. Я говорю иди с языком, который ты используешь, а не против него.
Скорее всего, разработчики языка оптимизируют язык под те идиомы, которые они пытаются поощрять. Если они вводят новое ключевое слово в язык, они, вероятно, думают, что имеет смысл быть ясным при создании нового экземпляра.
Код, написанный в соответствии с намерениями языка, будет повышаться с каждым выпуском. И код, избегающий ключевых конструкций языка, пострадает со временем.
РЕДАКТИРОВАТЬ: И это выходит далеко за рамки производительности. Я не могу сосчитать раз я слышал (или сказал) : «Почему, черт возьми , они делали что ?» при поиске странно выглядящего кода. Часто оказывается, что в то время, когда код был написан, для этого была какая-то «хорошая» причина. Следование Дао языка - ваша лучшая гарантия того, что ваш код не будет высмеян через несколько лет.
источник
Я написал пост о том, как решить проблему вызова конструктора без ключевого слова new.
Это в основном дидактическое, но оно показывает, как вы можете создавать конструкторы, которые работают с или без,
new
и не требует добавления шаблонного кода для тестированияthis
в каждом конструкторе.http://js-bits.blogspot.com/2010/08/constructors-without-using-new.html
Вот суть техники:
Вот как это использовать:
источник
arguments.callee
это здорово!surrogateConstructor
должно бытьsurrogateCtor
(или наоборот).Причина, по которой не используется ключевое слово new, проста:
Не используя его вообще, вы избегаете ловушки, которая возникает из-за случайного его пропуска. Шаблон построения, который использует YUI, является примером того, как можно полностью избежать нового ключевого слова "
В качестве альтернативы вы могли бы так это:
Но при этом вы рискуете, если кто-то забудет использовать ключевое слово new , а оператор this - fubar. AFAIK нет никакого преимущества для этого (кроме того, что вы привыкли к этому).
В конце дня: речь идет о защите. Можете ли вы использовать новое утверждение? Да. Это делает ваш код более опасным? Да.
Если вы когда-либо писали на C ++, это похоже на установку указателей на NULL после их удаления.
источник
Я думаю, что «новый» добавляет ясности в код. И ясность стоит всего. Приятно знать, что есть подводные камни, но избегать их, избегая ясности, не кажется мне подходящим.
источник
Случай 1:
new
не требуется и его следует избегатьСлучай 2:
new
обязательно, в противном случае вы получите ошибкуисточник
toString()
). Во всех остальных случаях используйте литералы. НеString('asd')
, а просто'asd'
, и неNumber(12)
, а просто12
.Array
:Array(5).fill(0)
очевидно, более читабельно, чем[undefined, undefined, undefined, undefined, undefined].fill(0)
и(var arr = []).length = 5; arr.fill(0);
new
with для типов объектов, соответствующих примитивным типам. Предлагаемый вами литерал не эквивалентенArray
вызову (try0 in …
), а остальное является синтаксической ошибкой :) В противном случае вы правы, хотя следует также отметить, что этоArray(5)
может быть неоднозначным, если вы рассматриваете несоответствующие реализации (и поэтому подражалArray.prototype.fill(…)
).Вот краткое изложение двух самых сильных аргументов за и против использования
new
оператора:Аргумент против
new
new
оператора, могут иметь катастрофические последствия, если они неправильно вызываются как обычные функции. Код функции в таком случае будет выполняться в области, где вызывается функция, а не в области локального объекта, как предполагалось. Это может привести к тому, что глобальные переменные и свойства будут перезаписаны с катастрофическими последствиями.function Func()
, а затем вызовFunc.prototype
и добавление к нему материала, чтобы можно было вызыватьnew Func()
для создания объекта, кажется некрасивым некоторым программистам, которые предпочитают использовать другой стиль наследования объектов по архитектурным и стилистическим причинам.Более подробно об этом аргументе можно прочитать в замечательной и лаконичной книге Дугласа Крокфорда «Javascript: The Good Parts». На самом деле проверить это в любом случае.
Аргумент в пользу
new
new
оператора вместе с назначением прототипа быстро.См . Пост Джона Резига для простого объяснения этой техники и для более глубокого объяснения модели наследования, которую он защищает.
источник
'use strict';
режима (или метода в вашей ссылке) # 2 Имеет синатический сахар в ES6 , однако поведение такое же, как и раньше.Я согласен с Pez и некоторые здесь.
Мне кажется очевидным, что «новое» - это самоописательное создание объекта, где шаблон YUI, описанный Грегом Дином, полностью скрыт .
Возможность того, что кто-то может написать
var bar = foo;
илиvar bar = baz();
где baz не является методом создания объекта, кажется гораздо более опасной.источник
Я думаю, что новое - зло, не потому, что если вы забудете использовать его по ошибке, это может вызвать проблемы, а потому, что оно испортит цепочку наследования, делая язык более сложным для понимания.
JavaScript основан на прототипах объектно-ориентированных. Следовательно, каждый объект ДОЛЖЕН быть создан из другого объекта
var newObj=Object.create(oldObj)
. Здесь oldObj называется прототипом newObj (следовательно, «на основе прототипа»). Это означает, что если свойство не найдено в newObj, то оно будет найдено в oldObj . Таким образом, по умолчанию newObj будет пустым объектом, но из-за цепочки прототипов он, похоже, имеет все значения oldObj .С другой стороны, если вы это сделаете
var newObj=new oldObj()
, прототип newObj это oldObj.prototype , который излишне сложен для понимания.Хитрость заключается в использовании
Именно внутри этой функции и только здесь должно использоваться новое. После этого просто используйте метод Object.create () . Способ решает проблему прототипа.
источник
var c = new Car()
это то же самое, что делатьvar c = Object.create(Car.prototype); Car.call(c)