javascript - JavaScript“new Array(n)”和“Array.prototype.map”古怪




6 Answers

看來,第一個例子

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 = [,,,];

由於map是在數組中的對象的上下文中運行的,我相信第一個map無法運行該函數,而第二個map卻無法運行該函數。

我在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)




有了ES6,你可以做[...Array(10)].map((a, b) => a) ,快速簡單!




陣列是不同的。 不同之處在於new Array(3)創建長度為3但沒有屬性的數組,而[undefined, undefined, undefined]創建一個數組,其長度為三個,三個屬性分別為“0”,“1”和“ 2“,每個值都是undefined 。 您可以使用in運算符來看到差異:

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

這源於一個稍微混淆的事實,即如果你試圖在JavaScript中獲得任何本地對象的不存在的屬性的值,它將返回undefined (而不是拋出一個錯誤,就像當你試圖引用一個不存在的變量),如果該屬性以前被undefined設置為undefined ,那麼它與您所得到的相同。




ES6解決方案:

[...Array(10)]

不過,它不適用於打印機(2.3)




不是一個錯誤。 這就是Array構造函數定義的工作方式。

來自MDC:

當您使用Array構造函數指定單個數字參數時,可以指定數組的初始長度。 以下代碼創建一個由五個元素組成的數組:

var billingMethod = new Array(5);

數組構造函數的行為取決於單個參數是否為數字。

.map()方法僅在數組的迭代元素中包含明確賦值的值。 即使是明確的undefined分配也會導致一個值被認為有資格包含在迭代中。 這似乎很奇怪,但它本質上是一個對像上的明確undefined屬性和缺少屬性之間的區別:

var x = { }, y = { z: undefined };
if (x.z === y.z) // true

對象x不具有稱為“z”的屬性,而對象y具有。 但是,在這兩種情況下,財產的“價值”都是undefined 。 在一個數組中,情況是相似的: length值確實隱含地對從零到length - 1所有元素執行賦值length - 1 。 因此.map()函數在用Array構造函數和數值參數新構造的數組上調用時不會執行任何操作(不會調用回調)。




在ECMAScript第6版規範中。

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步驟5。

方法mapreduceRightsomeforEachslicereducereduceRight ,Array的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);



Related