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




new-operator (6)

لا يوجد فرق بين الاثنين.

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

const obj = new Foo;

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

const obj = new Foo();

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


نقلا عن ديفيد فلاناغان 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() المفضل.


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

إليك الجزء الخاص بمواصفات ES6 التي تحدد كيفية عمل المتغيرين. تمرير متغير no-parentheses قائمة وسيطة فارغة.

ومن المثير للاهتمام أن النموذجين لهما معاني نحوية مختلفة. يحدث هذا عند محاولة الوصول إلى عضو في النتيجة.

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

كلاهما يفعل أشياء مختلفة.

أول يخلق كائن مع مدة التخزين التلقائي . يتم إنشاؤه واستخدامه ، ثم يخرج من النطاق عند انتهاء الكتلة الحالية ( { ... } ). إنها أبسط طريقة لإنشاء كائن ، وهي نفسها تمامًا عند كتابة int x = 0;

ينشئ الثاني كائنًا ذا مدة تخزين ديناميكية ويتيح شيئين:

  • تحكم دقيق في عمر الكائن ، لأنه لا يخرج من النطاق تلقائيًا ؛ يجب عليك تدميرها بشكل صريح باستخدام الكلمة الرئيسية delete ؛

  • إنشاء صفائف بحجم لا يعرف إلا في وقت التشغيل ، حيث يحدث إنشاء الكائن في وقت التشغيل. (لن أخوض في تفاصيل تخصيص المصفوفات الديناميكية هنا.)

لا هو المفضل يعتمد ذلك على ما تفعله أكثر ما يناسبك.

استخدم السابق إلا إذا كنت بحاجة لاستخدام هذا الأخير.

يجب أن يغطي كتابك C ++ هذا جيدًا. إذا لم يكن لديك واحد ، فلا تذهب إلى أبعد من ذلك حتى تقوم بشراء وقراءة ، عدة مرات ، واحدة من هذه .

حظا طيبا وفقك الله.

رمزك الأصلي مقطوع ، لأنه delete char sa char التي لم تكن new . في الواقع ، لا شيء new د سلسلة السلسلة C ؛ انها جاءت من سلسلة حرفية. delete هذا خطأ (على الرغم من أنه لن يؤدي إلى خطأ تجميع ، ولكن بدلاً من ذلك سلوك غير متوقع في وقت التشغيل).

عادة لا يجب أن يتحمل الجسم مسؤولية delete أي شيء لم يكن له نفسه new . يجب أن يكون هذا السلوك موثقة بشكل جيد. في هذه الحالة ، يتم كسر القاعدة بشكل كامل.





javascript new-operator