programing

new Array(count)를 통해 생성된 배열에서 map(지도) 메서드가 작동하지 않는 이유는 무엇입니까?

stoneblock 2023. 5. 24. 21:39

new Array(count)를 통해 생성된 배열에서 map(지도) 메서드가 작동하지 않는 이유는 무엇입니까?

Firefox-3.5.7/Firebug-1.5.3 및 Firefox-3.6.16/Firebug-1.6.2에서 이 문제를 발견했습니다.

Firebug를 실행할 때:

var x = new Array(3)
console.log(x) 
// [undefined, undefined, undefined]

var y = [undefined, undefined, undefined]
console.log(y) 
// [undefined, undefined, undefined]

console.log(x.constructor == y.constructor) // true

console.log( 
  x.map(function() { return 0; })
)
// [undefined, undefined, undefined]

console.log(
  y.map(function() { return 0; })
)
// [0, 0, 0]

이게 무슨 일입니까?버그인가요, 아니면 제가 사용법을 잘못 이해하고 있는 것인가요?new Array(3)?

배열의 길이만 알고 항목을 변환해야 하는 작업이 있었습니다.저는 다음과 같은 것을 하고 싶었습니다.

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));

첫 번째 예시는

x = new Array(3);

길이가 3이지만 요소가 없는 배열을 작성하므로 [0], [1] 및 [2] 인덱스는 작성되지 않습니다.

그리고 두 번째는 정의되지 않은 3개의 객체로 배열을 만듭니다. 이 경우 인덱스/속성 자체는 생성되지만 참조하는 객체는 정의되지 않습니다.

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

맵은 설정된 길이가 아닌 인덱스/속성 목록에서 실행되므로 인덱스/속성이 작성되지 않으면 실행되지 않습니다.

하면 ES6를 사용할 수 .[...Array(10)].map((a, b) => a)빠르고 쉽게!

ES6 솔루션:

[...Array(10)]

그러나 유형 스크립트(2.3)에서는 작동하지 않습니다.

다음에 대한 MDC 페이지:

[...]callback값이 할당된 배열의 인덱스에 대해서만 호출됩니다. [...]

[undefined]실제로 인덱스에 세터를 적용하여map repeat, 반할것에, 면반가.new Array(1)값기이다음인초덱기다니합화를스인본(▁index로 입니다.undefined그렇게map건너뜁니다.

저는 이것이 모든 반복 방법에 동일하다고 생각합니다.

배열이 다릅니다.은 다른점은입니다.new Array(3)길이가 3이지만 속성이 없는 배열을 만듭니다.[undefined, undefined, undefined]는 "및 " 3개의 "0", "1" 및 "2" 이 "3" 개 "3" 및 "3" 성 " 며 " 을 " 의 " 속 " 라 " 개 " 름 " 니 " 는 " 습 " 다 " 같 " 과 " 하 " 다 " 을 " 생 " 음 " 값 " 은 " 성 " 의 " 의 " 가 " 진 " 배 " 열 " 각 " 각 " ▁with " ▁properundefined여러분은 다을사용차수있다습니확인할이를 를 볼 수 .in연산자:

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

이것은 자바스크립트에 있는 어떤 네이티브 객체의 존재하지 않는 속성의 값을 얻으려고 하면 그것이 반환된다는 약간 혼란스러운 사실에서 비롯됩니다.undefined않는 하려고 할 때보다는), 이 이전에 (으)로 명시적으로 .undefined.

답변에서 로는, 다른답변자설이유로한명세히서에▁for,로유,Array(n).map작동하지 않습니다.그러나 ES2015에서는 다음과 같은 맵 기능을 사용할 수 있습니다.

let array1 = Array.from(Array(5), (_, i) => i + 1)
console.log('array1', JSON.stringify(array1)) // 1,2,3,4,5

let array2 = Array.from({length: 5}, (_, i) => (i + 1) * 2)
console.log('array2', JSON.stringify(array2)) // 2,4,6,8,10

ECMA스크립트 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 을 참조하십시오. ElementList5단계.

들방map,every,some,forEach,slice,reduce,reduceRight,filter는 Array의 합니다.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);

이것을 설명하는 가장 좋은 방법은 크롬이 처리하는 방식을 살펴보는 것이라고 생각합니다.

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

새 배열()은 길이가 3이지만 값이 없는 빈 배열을 반환합니다.를 할 때, 당이실할행을 실행합니다.x.map기술적으로 비어 있는 배열에서는 설정할 항목이 없습니다.

는 파어폭채 '우기만 '면이됩 '로 빈 을 '만 하면 .undefined가치가 없어도 말입니다.

저는 이것이 명백하게 버그가 아니라고 생각합니다. 단지 무슨 일이 일어나고 있는지 표현하는 서투른 방법일 뿐입니다.Chrome의 것이 실제로 배열에 아무것도 없다는 것을 보여주기 때문에 "더 정확하다"고 생각합니다.

벌레가 아닙니다.이렇게 어레이 생성자가 작동하도록 정의됩니다.

MDC에서:

배열 생성자를 사용하여 단일 숫자 매개변수를 지정할 때 배열의 초기 길이를 지정합니다.다음 코드는 5개 요소의 배열을 만듭니다.

var billingMethod = new Array(5);

배열 생성자의 동작은 단일 매개 변수가 숫자인지 여부에 따라 달라집니다.

.map()메서드는 값이 명시적으로 할당된 배열의 반복 요소에만 포함됩니다.의 명시적인 할당조차도.undefined값을 반복에 포함할 수 있는 것으로 간주합니다.이상해 보이지만, 본질적으로 명시적인 것 사이의 차이입니다.undefined개체의 속성과 누락된 속성:

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

목어x는 "라는 있지 , "z"는 "z"와 같은 속성을 가지고 있습니다.y은 "값"인 으로 나타납니다. 그러나 두 경우 모두 부동산의 "가치"는 것으로 보입니다.undefined 배에서 유사니다합열의 값. 값:length부터 0까지의 으로 값 합니다.length - 1..map()따라서 배열 생성자와 숫자 인수로 새로 구성된 배열에서 호출될 때 함수는 아무 것도 하지 않습니다(콜백을 호출하지 않습니다).

우연히 이 일을 당했어요.사용할 수 있다면 확실히 편리할 것입니다.Array(n).map.

Array(3)은 대략 대적인수.{length: 3}

[undefined, undefined, undefined]번호가 매겨진 속성을 만듭니다.
{0: undefined, 1: undefined, 2: undefined, length: 3}.

map() 구현은 정의된 속성에서만 작동합니다.

배열을 값으로 쉽게 채우기 위해 이 작업을 수행하고 있고 브라우저 지원 이유로 채우기를 사용할 수 없으며 for-loop을 수행하고 싶지 않다면 다음 작업도 수행할 수 있습니다.x = new Array(3).join(".").split(".").map(...빈 문자열 배열을 제공합니다.

상당히 추악하다고 말해야겠지만, 적어도 문제와 의도는 꽤 분명하게 전달되어 있습니다.

문제는 왜냐는 것이기 때문에, 이것은 JS가 어떻게 설계되었는지와 관련이 있습니다.

제가 이 행동을 설명할 수 있는 이유는 크게 두 가지입니다.

  • : : 진능성 : 주어진x = 10000그리고.new Array(x)을 0부터 10000까지 합니다.undefined가치.

  • 되지 않음 "정의되지 않음": "정의되지 않음a = [undefined, undefined]그리고.b = new Array(2),a[1]그리고.b[1]다 둘다돌것입니다올아를 반환합니다.undefined,그렇지만a[8]그리고.b[8] 또한돌것입니다올아다▁return▁also를 반환합니다.undefined그들이 사정권 밖에 있더라도.

은 적으로은, 법표기극입니다.empty x 3의 긴 목록을 설정하고 표시하지 않도록 하는 바로 가기입니다.undefined인 값undefined어쨌든 명시적으로 선언되지 않았기 때문입니다.

된 배열 주: 어진배열a = [0]그리고.a[9] = 9,console.log(a)돌아올 것입니다(10) [0, empty x 8, 9]명시적으로 선언된 두 값 사이의 차이를 반환하여 간격을 자동으로 메웁니다.

해결 방법으로 간단한 유틸리티 방법은 다음과 같습니다.

단순 지도 대상

function mapFor(toExclusive, callback) {
    callback = callback || function(){};
    var arr = [];
    for (var i = 0; i < toExclusive; i++) {
        arr.push(callback(i));
    }
    return arr;
};

var arr = mapFor(3, function(i){ return i; });
console.log(arr); // [0, 1, 2]
arr = mapFor(3);
console.log(arr); // [undefined, undefined, undefined]

전체 예제

다음은 선택적 시작 인덱스를 지정할 수 있는 보다 완전한 예(제니스 검사 포함)입니다.

function mapFor() {
var from, toExclusive, callback;
if (arguments.length == 3) {
    from = arguments[0];
    toExclusive = arguments[1];
    callback = arguments[2];
} else if (arguments.length == 2) {
    if (typeof arguments[1] === 'function') {
        from = 0;
        toExclusive = arguments[0];
        callback = arguments[1];
    } else {
        from = arguments[0];
        toExclusive = arguments[1];
    }
} else if (arguments.length == 1) {
    from = 0;
    toExclusive = arguments[0];
}

callback = callback || function () {};

var arr = [];
for (; from < toExclusive; from++) {
    arr.push(callback(from));
}
return arr;
}

var arr = mapFor(1, 3, function (i) { return i; });
console.log(arr); // [1, 2]
arr = mapFor(1, 3);
console.log(arr); // [undefined, undefined]
arr = mapFor(3);
console.log(arr); // [undefined, undefined, undefined]

카운트다운

콜백에 전달된 인덱스를 조작하면 거꾸로 카운트할 수 있습니다.

var count = 3;
var arr = arrayUtil.mapFor(count, function (i) {
    return count - 1 - i;
});
// arr = [2, 1, 0]

언급URL : https://stackoverflow.com/questions/5501581/why-does-the-map-method-apparently-not-work-on-arrays-created-via-new-arrayc