본문 바로가기

Array.prototype.map : Javascript Map function 자바스크립트 맵 함

카테고리 없음 by 낼스 2019. 7. 12.
# Array.prototype.map : Javascript Map function ■ [Array.map : https://developer.mozilla.org/ko/docs/Web/JavaScript/Reference/Global_Objects/Array/map](https://developer.mozilla.org/ko/docs/Web/JavaScript/Reference/Global_Objects/Array/map)
■ [참고 : http://www.wirfs-brock.com/allen/posts/166](http://www.wirfs-brock.com/allen/posts/166)
■ 문법 var new_array = arr.map(function callback(currentValue[, index[, array]]) { // new_array의 새 요소 반환 }[, thisArg]) : 매개변수 callback : 새로운 배열 요소를 생성하는 함수로 다음 세 가지 인수를 가집니다. currentValue : 배열의 요소 중, 현재 처리되고 있는 요소 indexOptional : 현재 처리되는 요소의 배열 내 인덱스 arrayOptional : map 메소드가 적용되는 본래 배열 thisArgOptional : callback을 실행할 때 this로 사용되는 값. : 반환 값 배열의 각 요소에 대해 실행한 함수(callback)의 결과를 모은 새로운 배열. ex) 배열에 들어있는 숫자들의 제곱근을 구하여 새로운 배열을 만들기 다음 코드는 숫자의 배열을 받아 각 숫자들의 제곱근이 들어있는 새로운 배열을 만듭니다. var numbers = [1, 4, 9]; var roots = numbers.map(Math.sqrt); // roots는 [1, 2, 3] // numbers는 그대로 [1, 4, 9] ex) map을 활용해 배열 속 객체를 재구성하기 다음 코드는 오브젝트의 배열을 받아 각 오브젝트를 다른 형태으로 재구성해 새로운 배열을 만듭니다. var kvArray = [{key:1, value:10}, {key:2, value:20}, {key:3, value: 30}]; var reformattedArray = kvArray.map(function(obj){ var rObj = {}; rObj[obj.key] = obj.value; return rObj; }); // reformattedArray는 [{1:10}, {2:20}, {3:30}] // kvArray는 그대로 // [{key:1, value:10}, // {key:2, value:20}, // {key:3, value: 30}] ex) 인자를 받는 함수를 사용하여 숫자 배열 재구성하기 다음 코드는 인자가 한개인 함수를 이용하여 map이 어떻게 동작하는지 나타냅니다. 인자인 배열과 안의 요소들은 map을 통해 순회하면서 원본 배열로 부터 자동으로 할당됩니다. var numbers = [1, 4, 9]; var doubles = numbers.map(function(num) { return num * 2; }); // doubles는 이제 [2, 8, 18] // numbers는 그대로 [1, 4, 9] ex) map을 포괄적으로 사용하기 아래 예제는 String에 map을 사용해서 각 문자의 ASCII 인코딩 값을 요소로 갖는 배열을 얻는 방법을 보여줍니다. var map = Array.prototype.map; var a = map.call('Hello World', function(x) { return x.charCodeAt(0); }); // a는 이제 [72, 101, 108, 108, 111, 32, 87, 111, 114, 108, 100] ex) map을 포괄적으로 사용하기 (querySelectorAll) 아래 예제는 querySelectorAll을 사용해서 수집된 객체들을 순회 처리하는 법을 보여줍니다. 이번 경우 체크한 옵션 박스를 콘솔에 프린트합니다. var elems = document.querySelectorAll('select option:checked'); var values = [].map.call(elems, function(obj) { return obj.value; }); 더 쉬운 방법은 Array.from()을 사용하는 것입니다. ex) 까다로운 사례 map에 하나의 인자(순회하는 원소)만 받는 콜백을 사용하는 경우가 많습니다. 그러나 어떤 함수는 대개 하나의 인자로 호출하지만 두 개 이상의 인자를 사용하는 경우도 있습니다. 이로 인해 어떤 경우 혼란스러울 수도 있습니다. // 아래 라인을 보시면... ['1', '2', '3'].map(parseInt); // 결과를 [1, 2, 3] 으로 기대할 수 있습니다. // 그러나 실제 결과는 [1, NaN, NaN] 입니다. // parseInt 함수는 보통 하나의 인자만 사용하지만, 두 개를 받을 수 있습니다. // 첫 번째 인자는 변환하고자 하는 표현이고 두 번째는 숫자로 변환할 때 사용할 진법입니다. // Array.prototype.map은 콜백에 세 가지 인자를 전달합니다. // 배열의 값, 값의 인덱스, 그리고 배열 // 세 번째 인자는 parseInt가 무시하지만 두 번째 인자는 아닙니다. // 따라서 혼란스러운 결과를 도출할 수 있습니다. 자세한 내용은 블로그 포스트를 참고하시길 바랍니다. function returnInt(element) { return parseInt(element, 10); } ['1', '2', '3'].map(returnInt); // [1, 2, 3] // 실제 결과가 예상한 대로 배열의 숫자와 같습니다. // 위와 같지만 더 간단한 화살표 표현식 ['1', '2', '3'].map(str => parseInt(str)); // 더 간단하게 해결할 수 있는 방법 ['1', '2', '3'].map(Number); // [1, 2, 3] // 그러나 `parseInt`와 달리 float이나 지수표현도 반환합니다. ['1.1', '2.2e2', '3e300'].map(Number); // [1.1, 220, 3e+300] ■ 폴리필 map은 ECMA-262 5판에 추가됐기 때문에 모든 구현체에 포함되지 않았습니다. 아래 스크립트를 처음에 추가하면 지원하지 않는 환경에서도 map을 사용할 수 있습니다. 본 알고리즘은 Object, TypeError, Array가 변형되지 않은 경우, 그리고callback.call 의 계산 값이 원본 Function.prototype.call과 같은 경우ECMA-262 5판에 명시된 것과 동일합니다. // Production steps of ECMA-262, Edition 5, 15.4.4.19 // Reference: http://es5.github.io/#x15.4.4.19 if (!Array.prototype.map) { Array.prototype.map = function(callback, thisArg) { var T, A, k; if (this == null) { throw new TypeError(' this is null or not defined'); } // 1. Let O be the result of calling ToObject passing the |this| // value as the argument. var O = Object(this); // 2. Let lenValue be the result of calling the Get internal // method of O with the argument "length". // 3. Let len be ToUint32(lenValue). var len = O.length >>> 0; // 4. If IsCallable(callback) is false, throw a TypeError exception. // See: http://es5.github.com/#x9.11 if (typeof callback !== 'function') { throw new TypeError(callback + ' is not a function'); } // 5. If thisArg was supplied, let T be thisArg; else let T be undefined. if (arguments.length > 1) { T = thisArg; } // 6. Let A be a new array created as if by the expression new Array(len) // where Array is the standard built-in constructor with that name and // len is the value of len. A = new Array(len); // 7. Let k be 0 k = 0; // 8. Repeat, while k < len while (k < len) { var kValue, mappedValue; // a. Let Pk be ToString(k). // This is implicit for LHS operands of the in operator // b. Let kPresent be the result of calling the HasProperty internal // method of O with argument Pk. // This step can be combined with c // c. If kPresent is true, then if (k in O) { // i. Let kValue be the result of calling the Get internal // method of O with argument Pk. kValue = O[k]; // ii. Let mappedValue be the result of calling the Call internal // method of callback with T as the this value and argument // list containing kValue, k, and O. mappedValue = callback.call(T, kValue, k, O); // iii. Call the DefineOwnProperty internal method of A with arguments // Pk, Property Descriptor // { Value: mappedValue, // Writable: true, // Enumerable: true, // Configurable: true }, // and false. // In browsers that support Object.defineProperty, use the following: // Object.defineProperty(A, k, { // value: mappedValue, // writable: true, // enumerable: true, // configurable: true // }); // For best browser support, use the following: A[k] = mappedValue; } // d. Increase k by 1. k++; } // 9. return A return A; }; } ■ 짧은 함수 var materials = [ 'Hydrogen', 'Helium', 'Lithium', 'Beryllium' ]; materials.map(function(material) { return material.length; }); // [8, 6, 7, 9] materials.map((material) => { return material.length; }); // [8, 6, 7, 9] materials.map(({length}) => length); // [8, 6, 7, 9]

댓글