Можем ли мы опустить скобки при создании объекта с помощью оператора «new»? - PullRequest
212 голосов
/ 14 июня 2010

Я видел объекты, создаваемые таким образом:

const obj = new Foo;

Но я подумал, что скобки не являются обязательными при создании объекта:

const obj = new Foo();

Является ли прежний способ создания объектов действительным и определенным в стандарте ECMAScript? Есть ли различия между первым способом создания объектов и последним? Один предпочтительнее другого?

Ответы [ 6 ]

220 голосов
/ 14 июня 2010

Цитирование Дэвид Фланаган 1 :

В особом случае, только для оператора new, JavaScript упрощает грамматику, позволяя опустить круглые скобки, если в вызове функции нет аргументов. Вот несколько примеров использования оператора new:

o = new Object;  // Optional parenthesis omitted here
d = new Date();  

...

Лично я всегда использую скобки, даже когда конструктор не принимает аргументов.

Кроме того, JSLint может повредить вашим чувствам, если вы опустите скобки. Он сообщает Missing '()' invoking a constructor, и, похоже, инструмент не может допустить пропуска скобок.


1 Дэвид Фланаган: JavaScript - полное руководство: 4-е издание (стр. 75)

61 голосов
/ 13 апреля 2016

Между ними есть различия:

  • new Date().toString() отлично работает и возвращает текущую дату
  • new Date.toString() throws " TypeError: Date.toString не является конструктором "

Это происходит потому, что new Date() и new Date имеют разный приоритет. Согласно MDN интересующая нас часть таблицы приоритетов операторов JavaScript выглядит так:

╔════════════╦═════════════════════════════╦═══════════════╦═════════════╗
║ Precedence ║        Operator type        ║ Associativity ║  Operators  ║
╠════════════╬═════════════════════════════╬═══════════════╬═════════════╣
║     18     ║ Member Access               ║ left-to-right ║ … . …       ║
║            ║ Computed Member Access      ║ left-to-right ║  … [ … ]    ║
║            ║ new (with argument list)    ║ n/a           ║ new … ( … ) ║
╠════════════╬═════════════════════════════╬═══════════════╬═════════════╣
║     17     ║ Function Call               ║ left-to-right ║ … ( … )     ║
║            ║ new (without argument list) ║ right-to-left ║ new …       ║
╚════════════╩═════════════════════════════╩═══════════════╩═════════════╝

Из этой таблицы следует, что:

  1. new Foo() имеет более высокий приоритет, чем new Foo

    new Foo() имеет тот же приоритет, что и . оператор

    new Foo имеет на один уровень более низкий приоритет, чем оператор .

    new Date().toString() отлично работает, потому что оценивается как (new Date()).toString()

    new Date.toString() throws " TypeError: Date.toString не является конструктором ", потому что . имеет более высокий приоритет, чем new Date (и выше, чем "вызов функции"), и выражение оценивается как (new (Date.toString))()

    Та же логика применима к оператору … [ … ].

  2. new Foo имеет справа налево ассоциативность и для new Foo() "ассоциативность" не применима. Я думаю, что на практике это не имеет никакого значения. Для получения дополнительной информации см. этот SO вопрос


Один из них предпочтительнее другого?

Зная все это, можно предположить, что new Foo() предпочтительнее.

14 голосов
/ 15 июля 2011

Я не думаю, что есть разница, когда вы используете оператор "new". Будьте осторожны с этой привычкой, так как эти две строки кода НЕ одинаковы:

var someVar = myFunc; // this assigns the function myFunc to someVar
var someOtherVar = myFunc(); // this executes myFunc and assigns the returned value to someOtherVar
13 голосов
/ 15 июля 2011

Если у вас нет аргументов для передачи, скобки являются необязательными.Пропускать их - просто синтаксический сахар.

6 голосов
/ 29 мая 2014

https://people.mozilla.org/~jorendorff/es6-draft.html#sec-new-operator-runtime-semantics-evaluation

Вот часть спецификации ES6, которая определяет, как работают два варианта.Вариант без скобок передает пустой список аргументов.

Интересно, что эти две формы имеют разные грамматические значения.Это появляется, когда вы пытаетесь получить доступ к члену результата.

new Array.length // fails because Array.length is the number 1, not a constructor
new Array().length // 0
3 голосов
/ 15 июля 2011

Нет никакой разницы между ними.

...