web-dev-qa-db-ja.com

「new」演算子を使用してオブジェクトを作成するときに括弧を省略できますか?

この方法でオブジェクトが作成されるのを見ました:

const obj = new Foo;

しかし、オブジェクトを作成するとき、括弧はオプションではないと考えました。

const obj = new Foo();

オブジェクトを作成する前者の方法は有効で、ECMAScript標準で定義されていますか?前者のオブジェクト作成方法と後者の方法に違いはありますか?一方が他方よりも優先されますか?

213
Behrang

引用 David Flanagan1

特別な場合として、new演算子の場合のみ、JavaScriptは関数呼び出しに引数がない場合に括弧を省略できるようにして、文法を簡素化します。 new演算子を使用した例を次に示します。

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

...
_

個人的には、コンストラクタが引数を取らない場合でも、常に括弧を使用します。

さらに、 JSLint は、括弧を省略すると感情を傷つける可能性があります。 Missing '()' invoking a constructorを報告しますが、括弧の省略を許容するツールのオプションはないようです。


1 デイビッド・フラナガン: JavaScript決定版ガイド:第4版 (75ページ)

221
Daniel Vassallo

2つの間に違いがあります。

  • new Date().toString()は完全に機能し、現在の日付を返します
  • new Date.toString() throws "TypeError:Date.toString is not constructor"

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の優先順位は、.演算子より1レベル低い

    new Date().toString()(new Date()).toString()として評価されるため完全に機能します

    new Date.toString() throws "TypeError:Date.toString is not a constructor" .new Dateよりも優先順位が高い(および「関数よりも高い」 Call ")と式は(new (Date.toString))()として評価されます

    同じロジックを… [ … ]演算子に適用できます。

  2. new Fooにはright-to-leftの結合性があり、new Foo()には「結合性」は適用できません。実際には違いはないと思います。詳細については、 this SO question


一方が他方よりも優先されますか?

すべてを知っているので、new Foo()が優先されると仮定できます。

63
traxium

「新しい」演算子を使用している場合、違いはないと思います。これらの2行のコードは同じではないため、この習慣に注意してください。

var someVar = myFunc; // this assigns the function myFunc to someVar
var someOtherVar = myFunc(); // this executes myFunc and assigns the returned value to someOtherVar
14
jbabey

渡す引数がない場合、括弧はオプションです。それらを省略することは単なる構文上の砂糖です。

13
Josh

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

以下は、2つのバリアントの動作方法を定義するES6仕様の一部です。括弧なしのバリアントは、空の引数リストを渡します。

興味深いことに、2つの形式の文法的な意味は異なります。これは、結果のメンバーにアクセスしようとすると発生します。

new Array.length // fails because Array.length is the number 1, not a constructor
new Array().length // 0
6
guest

2つの間に違いはありません。

3
Ivan