javascript - جافا سكريبت "new Array (n)" و "Array.prototype.map" غرابة





arrays firefox dictionary firebug (11)


المصفوفات مختلفة. الفرق هو أن new Array(3) تقوم بإنشاء مصفوفة بطول ثلاثة ولكن بدون خصائص ، في حين أن [undefined, undefined, undefined] يقوم بإنشاء مصفوفة ذات طول ثلاث وثلاث خصائص تسمى "0" و "1" و " 2 "، لكل منها قيمة undefined . يمكنك رؤية الفرق باستخدام عامل التشغيل:

"0" in new Array(3); // false
"0" in [undefined, undefined, undefined]; // true

ينبع ذلك من حقيقة مربكة قليلاً أنه إذا حاولت الحصول على قيمة خاصية غير موجودة لأي كائن أصلي في JavaScript ، فإنها تُرجع undefined (بدلاً من رمي خطأ ، كما يحدث عند محاولة الإشارة إلى عنصر غير موجود المتغير) ، وهو نفس ما تحصل عليه إذا تم تعيين الخاصية في وقت سابق على explictly إلى undefined .

لقد لاحظت هذا في Firefox-3.5.7 / Firebug-1.5.3 و Firefox-3.6.16 / Firebug-1.6.2

عندما أشعل Firebug:

    >>> x = new Array(3)
    [undefined, undefined, undefined]
    >>> y = [undefined, undefined, undefined]
    [undefined, undefined, undefined]

    >>> x.constructor == y.constructor
    true

    >>> x.map(function(){ return 0; })
    [undefined, undefined, undefined]
    >>> y.map(function(){ return 0; })
    [0, 0, 0]

ما الذي يحدث هنا؟ هل هذا خطأ ، أم أنا سوء فهم كيفية استخدام new Array(3) ؟




من صفحة MDC map :

[...] يتم استدعاء callback فقط لفهارس المصفوفة التي تم تعيين قيمة لها ؛ [...]

[undefined] يطبق بالفعل على المؤشر (es) بحيث يتم تكرار map ، في حين أن new Array(1) فقط بتهيئة الفهرس (es) بقيمة افتراضية undefined حتى تتخطىها map .

أعتقد أن هذا هو نفسه لجميع أساليب التكرار .




ركض للتو في هذا. من المؤكد أنه سيكون ملائماً لتكون قادرة على استخدام Array(n).map .

Array(3) تنتج تقريبًا {length: 3}

[undefined, undefined, undefined] ينشئ الخصائص المرقمة:
{0: undefined, 1: undefined, 2: undefined, length: 3} .

لا يعمل تطبيق الخريطة () إلا على خصائص محددة.




في مواصفات النسخة السادسة من ECMAScript.

new Array(3) يحدد length الخاصية فقط ولا يحدد خصائص الفهرس مثل {length: 3} . راجع https://www.ecma-international.org/ecma-262/6.0/index.html#sec-array-len الخطوة 9.

[undefined, undefined, undefined] سيحدد خصائص الفهرس وخصائص الطول مثل {0: undefined, 1: undefined, 2: undefined, length: 3} . راجع https://www.ecma-international.org/ecma-262/6.0/index.html#sec-runtime-semantics-arrayaccumulation ElementList Step 5.

أساليب map ، every ، some ، forEach ، slice ، reduce ، reduce reduceRight ، filter من صفيف سوف تحقق من خاصية الفهرس من خلال الأسلوب الداخلي HasProperty ، لذلك سوف new Array(3).map(v => 1) لا استدعاء رد الاتصال.

لمزيد من التفاصيل ، انظر https://www.ecma-international.org/ecma-262/6.0/index.html#sec-array.prototype.map

كيف تصلح؟

let a = new Array(3);
a.join('.').split('.').map(v => 1);

let a = new Array(3);
a.fill(1);

let a = new Array(3);
a.fill(undefined).map(v => 1);

let a = new Array(3);
[...a].map(v => 1);



كان لدي مهمة لم أكن أعرف سوى طول الصفيف وتحتاج إلى تحويل العناصر. أردت أن أفعل شيئًا كهذا:

let arr = new Array(10).map((val,idx) => idx);

لإنشاء مصفوفة بسرعة مثل هذا:

[0,1,2,3,4,5,6,7,8,9]

لكنها لم تنجح لأنها: أنظر جواب جوناثان لونوفسكي بضعة أجوبة.

قد يكون الحل لملء عناصر المصفوفة بأي قيمة (حتى مع غير معرّف) باستخدام Array.prototype.fill()

let arr = new Array(10).fill(undefined).map((val,idx) => idx);

console.log(new Array(10).fill(undefined).map((val, idx) => idx));

تحديث

حل آخر يمكن أن يكون:

let arr = Array.apply(null, Array(10)).map((val, idx) => idx);

console.log(Array.apply(null, Array(10)).map((val, idx) => idx));




مع ES6 ، يمكنك القيام [...Array(10)].map((a, b) => a) ، سريع وسهل!




إذا كنت تقوم بذلك من أجل ملء صفيف بقيم بسهولة ، فلا يمكنك استخدام fill لأسباب دعم المتصفح ولا تريد حقاً إجراء حلقة for-loop ، يمكنك أيضاً القيام بـ x = new Array(3).join(".").split(".").map(... التي سوف تعطيك مجموعة من السلاسل الفارغة.

لا بد لي من القول قبيح ، ولكن على الأقل يتم توصيل المشكلة والنية بوضوح تام.




في Chrome ، إذا أجريت new Array(3) ، فستحصل على [] ، لذا أعتقد أنك صادفت خطأً في المتصفح.




يبدو أن المثال الأول

x = new Array(3);

ينشئ مصفوفة بمؤشرات غير محددة.

والثاني يقوم بإنشاء مصفوفة مع مؤشرات إلى 3 كائنات غير محددة ، وفي هذه الحالة فإن المؤشرات الذاتية ليست غير محددة ، فقط الكائنات التي تشير إليها.

y = [undefined, undefined, undefined]
// The following is not equivalent to the above, it's the same as new Array(3)
y = [,,,];

عندما يتم تشغيل الخريطة في سياق الكائنات في المصفوفة أعتقد أن الخريطة الأولى تفشل في تشغيل الوظيفة على الإطلاق بينما يتم تشغيل الثانية في التشغيل.




أعتقد أن أفضل طريقة لشرح ذلك هي النظر إلى الطريقة التي يعالج بها Chrome.

>>> x = new Array(3)
[]
>>> x.length
3

إذن ما يحدث بالفعل هو أن Array () الجديد يقوم بإرجاع صفيف فارغ له طول 3 ، لكن بدون قيم. لذلك ، عند تشغيل x.map على صفيف فارغ تقنيًا ، لا يوجد شيء يمكن تعيينه.

فايرفوكس فقط "يملأ" تلك الفتحات الفارغة مع undefined حتى وإن لم يكن لديه قيم.

لا أعتقد أن هذا خطأ صريح ، فقط طريقة سيئة لتمثيل ما يجري. أفترض أن Chrome "أكثر صحة" لأنه يوضح أنه لا يوجد في الواقع أي شيء في الصفيف.




var index = haystack.indexOf(needle);




javascript arrays firefox dictionary firebug