javascript - هل يمكننا حذف الأقواس عند إنشاء كائن باستخدام المشغل "الجديد"؟




new-operator (4)

إذا لم يكن لديك وسيطات لتمرير ، الأقواس اختيارية. إغفالها هو مجرد السكر النحوي.

لقد رأيت كائنات يتم إنشاؤها بهذه الطريقة:

const obj = new Foo;

ولكني اعتقدت أن الأقواس ليست اختيارية عند إنشاء كائن:

const obj = new Foo();

هل الطريقة السابقة لإنشاء كائنات صحيحة ومعرّفة في معيار ECMAScript؟ هل هناك أي اختلافات بين الطريقة السابقة لإنشاء الأشياء وما بعدها؟ هو واحد يفضل على الآخر؟


لا أعتقد أن هناك أي فرق عند استخدام عامل التشغيل "الجديد". كن حريصًا على الدخول في هذه العادة ، لأن هذين السطرين من الشفرة ليسا متشابهين:

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

نقلا عن ديفيد فلاناغان 1 :

كحالة خاصة ، للمشغل new فقط ، يبسط JavaScript القواعد النحوية من خلال السماح بإلغاء الأقواس إذا لم تكن هناك وسيطات في استدعاء الدالة. فيما يلي بعض الأمثلة باستخدام المشغل new :

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

...

شخصيا ، أنا دائما استخدام قوس ، حتى عندما لا يأخذ المنشئ أي حجج.

بالإضافة إلى ذلك ، قد تؤذي JSLint مشاعرك إذا حذفت القوس. تشير إلى Missing '()' invoking a constructor ، ولا يبدو أن هناك خيارًا للأداة التي تتسامح مع إغفال الأقواس.

1 David Flanagan: JavaScript the definitive Guide: 4th Edition (page 75)


هناك اختلافات بين الاثنين:

  • new Date().toString() يعمل تماما ويعود التاريخ الحالي
  • new Date.toString() throws " TypeError: Date.toString غير منشئ "

يحدث ذلك لأن new Date() new Date لهما أسبقية مختلفة. وفقًا لـ MDN فإن جزء جدول MDN جافا سكريبت الذي نهتم به يبدو كالتالي:

╔════════════╦═════════════════════════════╦═══════════════╦═════════════╗
║ 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() "associativity" جديد لا ينطبق. أعتقد أنه من الناحية العملية لا يحدث أي فرق. للحصول على معلومات إضافية ، راجع سؤال SO this

هو واحد يفضل على الآخر؟

معرفة كل ما يمكن أن يفترض أن new Foo() المفضل.





new-operator