배열은 다양한 메소드를 제공합니다. 작업을 더 쉽게 하기 위해 이 장에서는 그룹으로 나뉩니다.
우리는 처음이나 끝에서 항목을 추가하고 제거하는 방법을 이미 알고 있습니다.
arr.push(...items)
– 끝에 항목을 추가합니다.
arr.pop()
– 끝에서 항목을 추출합니다.
arr.shift()
– 처음부터 항목을 추출합니다.
arr.unshift(...items)
– 시작 부분에 항목을 추가합니다.
다음은 몇 가지 다른 내용입니다.
배열에서 요소를 삭제하는 방법은 무엇입니까?
배열은 객체이므로 delete
사용해 볼 수 있습니다.
let arr = ["나", "가기", "집"]; 삭제 arr[1]; // "이동" 제거 경고( arr[1] ); // 한정되지 않은 // 이제 arr = ["나", , "집"]; 경고(arr.length); // 3
요소가 제거되었지만 배열에는 여전히 3개의 요소가 있습니다. arr.length == 3
임을 알 수 있습니다.
delete obj.key
key
로 값을 제거하기 때문에 이는 자연스러운 현상입니다. 그게 전부입니다. 물체에는 괜찮습니다. 그러나 배열의 경우 일반적으로 나머지 요소가 이동하여 해제된 위치를 차지하기를 원합니다. 이제 배열이 더 짧아질 것으로 예상됩니다.
따라서 특별한 방법을 사용해야 합니다.
arr.splice 메소드는 배열을 위한 스위스 군용 칼입니다. 요소 삽입, 제거, 교체 등 모든 작업을 수행할 수 있습니다.
구문은 다음과 같습니다.
arr.splice(start[, deleteCount, elem1, ..., elemN])
이는 인덱스 start
부터 시작하여 arr
수정합니다. deleteCount
요소를 제거한 다음 해당 위치에 elem1, ..., elemN
삽입합니다. 제거된 요소의 배열을 반환합니다.
이 방법은 예제를 통해 이해하기 쉽습니다.
삭제부터 시작해 보겠습니다.
let arr = ["나", "공부", "자바스크립트"]; arr.splice(1, 1); // 인덱스 1에서 요소 1개 제거 경고(arr); // ["나", "자바스크립트"]
쉽지요? 인덱스 1
부터 시작하여 1
요소를 제거했습니다.
다음 예에서는 3개의 요소를 제거하고 이를 다른 2개의 요소로 대체합니다.
let arr = ["나", "공부", "자바스크립트", "맞아", "지금"]; // 첫 번째 요소 3개를 제거하고 다른 요소로 교체 arr.splice(0, 3, "Let's", "dance"); Alert( arr ) // 이제 ["Let's", "dance", "right", "now"]
여기에서 splice
제거된 요소의 배열을 반환하는 것을 볼 수 있습니다.
let arr = ["나", "공부", "자바스크립트", "맞아", "지금"]; // 첫 번째 요소 2개 제거 제거하자 = arr.splice(0, 2); 경고( 제거됨 ); // "I", "study" <-- 제거된 요소의 배열
splice
방법을 사용하면 요소를 제거하지 않고 삽입할 수도 있습니다. 이를 위해서는 deleteCount
0
으로 설정해야 합니다.
let arr = ["나", "공부", "자바스크립트"]; // 인덱스 2에서 // 0 삭제 // 그런 다음 "complex"와 "언어"를 삽입합니다. arr.splice(2, 0, "복잡함", "언어"); 경고(arr); // "나", "공부", "복잡함", "언어", "자바스크립트"
음수 인덱스 허용
여기와 다른 배열 방법에서는 음수 인덱스가 허용됩니다. 다음과 같이 배열 끝에서 위치를 지정합니다.
arr = [1, 2, 5]로 설정; // 인덱스 -1부터(끝에서 한 단계) // 0개 요소 삭제, // 그런 다음 3과 4를 삽입합니다. arr.splice(-1, 0, 3, 4); 경고(arr); // 1,2,3,4,5
arr.slice 메서드는 비슷한 모양의 arr.splice
보다 훨씬 간단합니다.
구문은 다음과 같습니다.
arr.slice([시작], [끝])
인덱스 start
부터 end
( end
제외) 모든 항목을 복사하는 새 배열을 반환합니다. start
과 end
모두 음수일 수 있으며, 이 경우 배열 끝에서의 위치가 가정됩니다.
문자열 메소드 str.slice
와 유사하지만 하위 문자열 대신 하위 배열을 만듭니다.
예를 들어:
let arr = ["t", "e", "s", "t"]; 경고( arr.slice(1, 3) ); // e,s (1부터 3까지 복사) 경고( arr.slice(-2) ); // s,t (-2부터 끝까지 복사)
인수 없이 호출할 수도 있습니다. arr.slice()
arr
의 복사본을 만듭니다. 이는 원래 배열에 영향을 주지 않아야 하는 추가 변환을 위한 복사본을 얻는 데 자주 사용됩니다.
arr.concat 메소드는 다른 배열의 값과 추가 항목을 포함하는 새 배열을 생성합니다.
구문은 다음과 같습니다.
arr.concat(arg1, arg2...)
배열이든 값이든 원하는 수의 인수를 허용합니다.
결과는 arr
, arg1
, arg2
등의 항목을 포함하는 새로운 배열입니다.
인수 argN
배열이면 해당 요소가 모두 복사됩니다. 그렇지 않으면 인수 자체가 복사됩니다.
예를 들어:
arr = [1, 2]; // arr 및 [3,4]에서 배열을 만듭니다. 경고( arr.concat([3, 4]) ); // 1,2,3,4 // arr, [3,4], [5,6]에서 배열을 만듭니다. 경고( arr.concat([3, 4], [5, 6]) ); // 1,2,3,4,5,6 // arr 및 [3,4]에서 배열을 만든 다음 값 5와 6을 추가합니다. 경고( arr.concat([3, 4], 5, 6) ); // 1,2,3,4,5,6
일반적으로 배열의 요소만 복사합니다. 다른 객체는 배열처럼 보이더라도 전체적으로 추가됩니다.
arr = [1, 2]; arrayLike = {하자 0: "뭔가", 길이: 1 }; 경고( arr.concat(arrayLike) ); // 1,2,[객체 객체]
…그러나 배열과 유사한 객체에 특별한 Symbol.isConcatSpreadable
속성이 있는 경우 concat
에 의해 배열로 처리됩니다. 해당 요소가 대신 추가됩니다.
arr = [1, 2]; arrayLike = {하자 0: "뭔가", 1: "다른", [Symbol.isConcatSpreadable]: 사실, 길이: 2 }; 경고( arr.concat(arrayLike) ); // 1,2,무언가,다른 것
arr.forEach 메소드를 사용하면 배열의 모든 요소에 대해 함수를 실행할 수 있습니다.
구문:
arr.forEach(함수(항목, 인덱스, 배열) { // ... 항목으로 작업 수행 });
예를 들어, 다음은 배열의 각 요소를 보여줍니다.
// 각 요소 호출에 대해 경고 ["빌보", "간달프", "나즈굴"].forEach(alert);
그리고 이 코드는 대상 배열에서의 위치에 대해 더 자세히 설명합니다.
["Bilbo", "Gandalf", "Nazgul"].forEach((item, index, array) => { Alert(`${item}은(는) ${array}의 인덱스 ${index}에 있습니다.`); });
함수의 결과(어떤 것이든 반환되는 경우)는 버려지고 무시됩니다.
이제 배열에서 검색하는 메서드를 살펴보겠습니다.
arr.indexOf 및 arr.includes 메서드는 비슷한 구문을 가지며 기본적으로 문자열과 동일하지만 문자 대신 항목에 대해 작동합니다.
arr.indexOf(item, from)
– index from
에서 시작하는 item
찾고 해당 항목이 발견된 인덱스를 반환합니다. 그렇지 않으면 -1
입니다.
arr.includes(item, from)
– index from
에서 시작하는 item
찾고, 발견되면 true
반환합니다.
일반적으로 이러한 메소드는 검색할 item
하나의 인수로만 사용됩니다. 기본적으로 검색은 처음부터 이루어집니다.
예를 들어:
arr = [1, 0, false]로 설정합니다. 경고( arr.indexOf(0) ); // 1 경고( arr.indexOf(false) ); // 2 경고( arr.indexOf(null) ); // -1 경고( arr.includes(1) ); // 진실
indexOf
비교를 위해 엄격한 동등성 ===
사용합니다. 따라서 false
찾으면 0이 아닌 정확히 false
찾습니다.
item
배열에 존재하고 인덱스가 필요하지 않은지 확인하려면 arr.includes
가 선호됩니다.
arr.lastIndexOf 메소드는 indexOf
와 동일하지만 오른쪽에서 왼쪽으로 검색합니다.
과일 = ['사과', '오렌지', '사과'] 경고(fruits.indexOf('Apple') ); // 0(첫 번째 Apple) 경고(fruits.lastIndexOf('Apple') ); // 2 (마지막 사과)
includes
메소드는 NaN
올바르게 처리합니다.
includes
의 사소하지만 주목할 만한 기능은 indexOf
와 달리 NaN
올바르게 처리한다는 것입니다.
const arr = [NaN]; 경고( arr.indexOf(NaN) ); // -1 (잘못, 0이어야 함) Alert( arr.includes(NaN) );// true (올바름)
그 이유는 includes
훨씬 나중에 JavaScript에 추가되었으며 내부적으로 최신 비교 알고리즘을 사용하기 때문입니다.
객체 배열이 있다고 상상해 보세요. 특정 조건을 가진 객체를 어떻게 찾나요?
여기서 arr.find(fn) 메소드가 유용합니다.
구문은 다음과 같습니다.
결과 = arr.find(function(item, index, array) { // true가 반환되면 항목이 반환되고 반복이 중지됩니다. // 거짓 시나리오의 경우 정의되지 않음을 반환합니다. });
이 함수는 배열의 요소에 대해 하나씩 호출됩니다.
item
요소입니다.
index
해당 인덱스입니다.
array
배열 자체입니다.
true
반환하면 검색이 중지되고 item
반환됩니다. 아무것도 발견되지 않으면 undefined
이 반환됩니다.
예를 들어, 각각 id
및 name
필드가 있는 사용자 배열이 있습니다. id == 1
인 것을 찾아봅시다:
사용자 = [ {id: 1, 이름: "John"}, {id: 2, 이름: "피트"}, {id: 3, 이름: "Mary"} ]; let user = users.find(item => item.id == 1); 경고(사용자.이름); // 존
실생활에서는 객체 배열이 흔한 일이므로 find
메소드는 매우 유용합니다.
예제에서는 하나의 인수를 사용하여 item => item.id == 1
함수를 find
위해 제공합니다. 이는 일반적이며 이 함수의 다른 인수는 거의 사용되지 않습니다.
arr.findIndex 메소드는 동일한 구문을 가지고 있지만 요소 자체 대신 요소가 발견된 인덱스를 반환합니다. 아무것도 발견되지 않으면 -1
값이 반환됩니다.
arr.findLastIndex 메서드는 findIndex
와 비슷하지만 lastIndexOf
와 비슷하게 오른쪽에서 왼쪽으로 검색합니다.
예는 다음과 같습니다.
사용자 = [ {id: 1, 이름: "John"}, {id: 2, 이름: "피트"}, {id: 3, 이름: "메리"}, {id: 4, 이름: "John"} ]; // 첫 번째 John의 인덱스를 찾습니다. Alert(users.findIndex(user => user.name == 'John')); // 0 // 마지막 John의 색인을 찾습니다. Alert(users.findLastIndex(user => user.name == 'John')); // 3
find
메소드는 함수가 true
반환하게 만드는 단일(첫 번째) 요소를 찾습니다.
많을 경우 arr.filter(fn)를 사용할 수 있습니다.
구문은 find
와 유사하지만 filter
일치하는 모든 요소의 배열을 반환합니다.
결과 = arr.filter(function(item, index, array) { // true 항목이 결과에 푸시되고 반복이 계속되는 경우 // 아무것도 발견되지 않으면 빈 배열을 반환합니다. });
예를 들어:
사용자 = [ {id: 1, 이름: "John"}, {id: 2, 이름: "피트"}, {id: 3, 이름: "Mary"} ]; // 처음 두 사용자의 배열을 반환합니다. let someUsers = users.filter(item => item.id < 3); 경고(someUsers.length); // 2
배열을 변환하고 재정렬하는 메서드로 넘어가겠습니다.
arr.map 메소드는 가장 유용하고 자주 사용되는 메소드 중 하나입니다.
배열의 각 요소에 대해 함수를 호출하고 결과 배열을 반환합니다.
구문은 다음과 같습니다.
결과 = arr.map(function(item, index, array) { // 항목 대신 새 값을 반환합니다. });
예를 들어, 여기서는 각 요소를 길이로 변환합니다.
let lengths = ["Bilbo", "Gandalf", "Nazgul"].map(item => item.length); 경고(길이); // 5,7,6
arr.sort() 호출은 배열을 제자리에 정렬하여 요소 순서를 변경합니다.
또한 정렬된 배열을 반환하지만 arr
자체가 수정되므로 반환된 값은 일반적으로 무시됩니다.
예를 들어:
arr = [ 1, 2, 15 ]; // 메소드는 arr의 내용을 재정렬합니다. arr.sort(); 경고(arr); // 1, 15, 2
결과에서 이상한 점을 발견하셨나요?
순서는 1, 15, 2
되었습니다. 잘못된. 그런데 왜?
항목은 기본적으로 문자열로 정렬됩니다.
말 그대로 모든 요소는 비교를 위해 문자열로 변환됩니다. 문자열의 경우 사전식 순서가 적용되며 실제로 "2" > "15"
입니다.
자체 정렬 순서를 사용하려면 arr.sort()
의 인수로 함수를 제공해야 합니다.
함수는 두 개의 임의 값을 비교하고 다음을 반환해야 합니다.
함수 비교(a, b) { (a > b)인 경우 1을 반환합니다. //첫 번째 값이 두 번째 값보다 큰 경우 (a == b)인 경우 0을 반환합니다. // 값이 같은 경우 (a < b)인 경우 -1을 반환합니다. //첫 번째 값이 두 번째 값보다 작은 경우 }
예를 들어 숫자로 정렬하려면 다음과 같이 하세요.
함수 비교숫자(a, b) { (a > b)인 경우 1을 반환합니다. (a == b)인 경우 0을 반환합니다. (a < b)인 경우 -1을 반환합니다. } arr = [ 1, 2, 15 ]; arr.sort(비교숫자); 경고(arr); // 1, 2, 15
이제 의도한 대로 작동합니다.
한 걸음 물러서서 무슨 일이 일어나고 있는지 생각해 봅시다. arr
무엇이든 배열이 될 수 있습니다. 그렇죠? 여기에는 숫자, 문자열, 객체 등이 포함될 수 있습니다. 우리 는 일부 항목 의 세트 를 가지고 있습니다 . 이를 정렬하려면 해당 요소를 비교하는 방법을 아는 순서 지정 함수가 필요합니다. 기본값은 문자열 순서입니다.
arr.sort(fn)
메소드는 일반적인 정렬 알고리즘을 구현합니다. 내부적으로 어떻게 작동하는지 신경 쓸 필요가 없습니다(대부분의 경우 최적화된 Quicksort 또는 Timsort). 이는 배열을 탐색하고, 제공된 함수를 사용하여 해당 요소를 비교하고 순서를 변경합니다. 우리에게 필요한 것은 비교를 수행하는 fn
제공하는 것뿐입니다.
그건 그렇고, 어떤 요소가 비교되는지 알고 싶다면 해당 요소에 경고하는 것을 방해하는 것은 없습니다.
[1, -2, 15, 2, 0, 8].sort(함수(a, b) { 경고( a + " <> " + b ); a-b를 반환합니다. });
알고리즘은 프로세스에서 한 요소를 다른 여러 요소와 비교할 수 있지만 가능한 한 적은 수의 비교를 시도합니다.
비교 함수는 임의의 숫자를 반환할 수 있습니다.
실제로 비교 함수는 "더 크다"는 양수를 반환하고 "더 작다"는 음수를 반환하는 데만 필요합니다.
이를 통해 더 짧은 함수를 작성할 수 있습니다.
arr = [ 1, 2, 15 ]; arr.sort(function(a, b) { return a - b; }); 경고(arr); // 1, 2, 15
최고의 화살표 기능
화살표 기능을 기억하시나요? 더 깔끔한 정렬을 위해 여기에서 사용할 수 있습니다.
arr.sort( (a, b) => a - b );
이는 위의 더 긴 버전과 정확히 동일하게 작동합니다.
문자열에 localeCompare
사용
문자열 비교 알고리즘을 기억하시나요? 기본적으로 문자를 코드별로 비교합니다.
많은 알파벳의 경우 Ö
와 같은 문자를 올바르게 정렬하려면 str.localeCompare
메서드를 사용하는 것이 좋습니다.
예를 들어, 독일어로 몇 가지 국가를 정렬해 보겠습니다.
let 국가 = ['외스터라이히', '안도라', '베트남']; 경고( 국가.정렬( (a, b) => a > b ? 1 : -1) ); // 안도라, 베트남, Österreich (잘못됨) 경고( 국가.정렬( (a, b) => a.localeCompare(b) ) ); // 안도라,외스터라이히,베트남 (맞습니다!)
arr.reverse 메소드는 arr
의 요소 순서를 반대로 바꿉니다.
예를 들어:
arr = [1, 2, 3, 4, 5]로 설정합니다. arr.reverse(); 경고(arr); // 5,4,3,2,1
또한 반전 후에 배열 arr
반환합니다.
실제 상황은 다음과 같습니다. 우리는 메시징 앱을 작성하고 있으며 그 사람은 쉼표로 구분된 수신자 목록인 John, Pete, Mary
입력합니다. 그러나 우리에게는 단일 문자열보다 이름 배열이 훨씬 더 편할 것입니다. 그것을 얻는 방법?
str.split(delim) 메소드가 바로 그 일을 합니다. 주어진 구분 기호 delim
에 따라 문자열을 배열로 분할합니다.
아래 예에서는 쉼표와 공백으로 구분합니다.
let names = '빌보, 간달프, 나즈굴'; arr = names.split(', '); for (arr의 이름을 알려주세요) { Alert( `${name} 님에게 보내는 메시지입니다.` ); // Bilbo(및 다른 이름)에게 보내는 메시지 }
split
방법에는 선택적 두 번째 숫자 인수(배열 길이 제한)가 있습니다. 제공된 경우 추가 요소는 무시됩니다. 실제로는 거의 사용되지 않습니다.
let arr = '빌보, 간달프, 나즈굴, 사루만'.split(', ', 2); 경고(arr); // 빌보, 간달프
문자로 분할
빈 s
사용하여 split(s)
을 호출하면 문자열이 문자 배열로 분할됩니다.
str = "테스트"; 경고( str.split('') ); // 시험
arr.join(glue) 호출은 split
과 반대로 수행됩니다. arr
항목 사이를 glue
로 연결하여 일련의 항목을 생성합니다.
예를 들어:
let arr = ['빌보', '간달프', '나즈굴']; str = arr.join(';'); // ;를 사용하여 배열을 문자열에 붙입니다. 경고(str); // 빌보;간달프;나즈굴
배열을 반복해야 하는 경우 forEach
, for
또는 for..of
사용할 수 있습니다.
각 요소에 대한 데이터를 반복하고 반환해야 하는 경우 map
사용할 수 있습니다.
arr.reduce 및 arr.reduceRight 메소드도 해당 유형에 속하지만 조금 더 복잡합니다. 배열을 기반으로 단일 값을 계산하는 데 사용됩니다.
구문은 다음과 같습니다.
let value = arr.reduce(function(accumulator, item, index, array) { // ... }, [초기의]);
이 함수는 모든 배열 요소에 차례로 적용되며 그 결과를 다음 호출에 "계속"합니다.
인수:
accumulator
– 이전 함수 호출의 결과이며 initial
과 동일합니다( initial
이 제공되는 경우).
item
– 현재 배열 항목입니다.
index
– 위치입니다.
array
– 배열입니다.
함수가 적용되면서 이전 함수 호출의 결과가 첫 번째 인수로 다음 함수에 전달됩니다.
따라서 첫 번째 인수는 본질적으로 모든 이전 실행의 결합된 결과를 저장하는 누산기입니다. 그리고 결국은 reduce
의 결과가 됩니다.
복잡해 보이죠?
이를 이해하는 가장 쉬운 방법은 예제를 보는 것입니다.
여기서는 한 줄로 배열의 합계를 얻습니다.
arr = [1, 2, 3, 4, 5]로 설정합니다. 결과 = arr.reduce((sum, current) => sum + current, 0); 경고(결과); // 15
reduce
에 전달된 함수는 일반적으로 2개의 인수만 사용합니다.
무슨 일이 일어나고 있는지 자세히 살펴보겠습니다.
첫 번째 실행에서 sum
은 initial
값( reduce
의 마지막 인수)이고 0
이며 current
첫 번째 배열 요소인 1
입니다. 따라서 함수 결과는 1
입니다.
두 번째 실행에서는 sum = 1
이고 여기에 두 번째 배열 요소( 2
)를 추가하고 반환합니다.
세 번째 실행에서는 sum = 3
이고 여기에 요소를 하나 더 추가하는 식입니다.
계산 흐름:
또는 각 행이 다음 배열 요소에 대한 함수 호출을 나타내는 테이블 형식입니다.
sum | current | 결과 | |
---|---|---|---|
첫 번째 전화 | 0 | 1 | 1 |
두 번째 전화 | 1 | 2 | 3 |
세 번째 전화 | 3 | 3 | 6 |
네 번째 전화 | 6 | 4 | 10 |
다섯 번째 전화 | 10 | 5 | 15 |
여기서 우리는 이전 호출의 결과가 다음 호출의 첫 번째 인수가 되는 방식을 명확하게 볼 수 있습니다.
초기값을 생략할 수도 있습니다:
arr = [1, 2, 3, 4, 5]로 설정합니다. // Reduce에서 초기값을 제거함(0 없음) 결과 = arr.reduce((sum, current) => sum + current); 경고(결과); // 15
결과는 동일합니다. 왜냐하면 초기값이 없으면 reduce
배열의 첫 번째 요소를 초기값으로 취하고 두 번째 요소부터 반복을 시작하기 때문입니다.
계산표는 첫 번째 행을 제외하고 위와 동일합니다.
그러나 그러한 사용에는 극도의 주의가 필요합니다. 배열이 비어 있으면 초기값 없이 호출을 reduce
오류가 발생합니다.
예는 다음과 같습니다.
arr = []; // 오류: 초기값이 없는 빈 배열 감소 // 초기 값이 존재하는 경우, 축소는 빈 arr에 대해 이를 반환합니다. arr.reduce((sum, current) => sum + current);
따라서 항상 초기값을 지정하는 것이 좋습니다.
arr.reduceRight 메소드는 동일하지만 오른쪽에서 왼쪽으로 이동합니다.
배열은 별도의 언어 유형을 형성하지 않습니다. 그것들은 객체를 기반으로 합니다.
따라서 typeof
일반 객체와 배열을 구별하는 데 도움이 되지 않습니다.
경고({} 유형); // 물체 경고(유형의 []); // 객체 (동일)
…그러나 배열은 너무 자주 사용되므로 이를 위한 특별한 메서드인 Array.isArray(value)가 있습니다. value
이 배열이면 true
반환하고, 그렇지 않으면 false
반환합니다.
경고(Array.isArray({})); // 거짓 경고(Array.isArray([])); // 진실
find
, filter
, map
과 같은 함수를 호출하는 거의 모든 배열 메소드는 sort
를 제외하고 선택적 추가 매개변수 thisArg
허용합니다.
해당 매개변수는 거의 사용되지 않으므로 위 섹션에서는 설명하지 않습니다. 그러나 완전성을 위해서는 이를 다루어야 합니다.
이러한 메서드의 전체 구문은 다음과 같습니다.
arr.find(func, thisArg); arr.filter(func, thisArg); arr.map(func, thisArg); // ... // thisArg는 선택적 마지막 인수입니다.
func
의 경우 thisArg
매개변수 값은 this
됩니다.
예를 들어, 여기에서는 army
개체의 메서드를 필터로 사용하고 thisArg
컨텍스트를 전달합니다.
군대 = { 최소나이: 18, 최대 연령: 27, canJoin(사용자) { return user.age >= this.minAge && user.age < this.maxAge; } }; 사용자 = [ {나이: 16}, {나이: 20}, {나이: 23}, {나이: 30} ]; // Army.canJoin이 true를 반환하는 사용자를 찾습니다. 군인을 보자 = users.filter(army.canJoin, 군대); 경고(군인.길이); // 2 경고(군인[0].나이); // 20 경고(군인[1].나이); // 23
위의 예에서 users.filter(army.canJoin)
사용한 경우 army.canJoin
this=undefined
과 함께 독립 실행형 함수로 호출되어 즉각적인 오류가 발생합니다.
users.filter(army.canJoin, army)
호출은 동일한 작업을 수행하는 users.filter(user => army.canJoin(user))
로 대체될 수 있습니다. 후자는 대부분의 사람들이 이해하기 쉽기 때문에 더 자주 사용됩니다.
배열 방법에 대한 치트 시트:
요소를 추가/제거하려면:
push(...items)
– 끝에 항목을 추가합니다.
pop()
– 끝에서 항목을 추출합니다.
shift()
– 처음부터 항목을 추출합니다.
unshift(...items)
– 시작 부분에 항목을 추가합니다.
splice(pos, deleteCount, ...items)
– 인덱스 pos
에서 deleteCount
요소를 삭제하고 items
삽입합니다.
slice(start, end)
– 새 배열을 만들고 인덱스 start
부터 end
(포함되지 않음) 요소를 배열에 복사합니다.
concat(...items)
– 새 배열을 반환합니다. 현재 배열의 모든 멤버를 복사하고 여기에 items
추가합니다. items
중 하나라도 배열이면 해당 요소가 사용됩니다.
요소를 검색하려면:
indexOf/lastIndexOf(item, pos)
– pos
위치에서 시작하는 item
찾고, 찾을 수 없으면 인덱스를 반환하거나 -1
반환합니다.
includes(value)
– 배열에 value
있으면 true
반환하고, 그렇지 않으면 false
반환합니다.
find/filter(func)
– 함수를 통해 요소를 필터링하고 true
반환하는 첫 번째/모든 값을 반환합니다.
findIndex
find
와 비슷하지만 값 대신 인덱스를 반환합니다.
요소를 반복하려면 다음을 수행하십시오.
forEach(func)
– 모든 요소에 대해 func
호출하고 아무것도 반환하지 않습니다.
배열을 변환하려면 다음을 수행하십시오.
map(func)
– 모든 요소에 대해 func
호출한 결과로부터 새 배열을 만듭니다.
sort(func)
– 배열을 제자리에서 정렬한 다음 반환합니다.
reverse()
– 배열을 제자리에서 뒤집은 다음 반환합니다.
split/join
– 문자열을 배열로 변환하고 그 반대로 변환합니다.
reduce/reduceRight(func, initial)
– 각 요소에 대해 func
호출하고 호출 사이에 중간 결과를 전달하여 배열에 대한 단일 값을 계산합니다.
추가로:
Array.isArray(value)
value
배열인지 확인하고, 배열이면 true
반환하고, 그렇지 않으면 false
반환합니다.
sort
, reverse
및 splice
메서드는 배열 자체를 수정한다는 점에 유의하세요.
이러한 방법은 가장 많이 사용되는 방법이며 사용 사례의 99%를 포괄합니다. 그러나 다른 것들은 거의 없습니다:
arr.some(fn)/arr.every(fn) 배열을 확인하십시오.
fn
함수는 map
과 유사하게 배열의 각 요소에 대해 호출됩니다. 일부/모든 결과가 true
이면 true
반환하고, 그렇지 않으면 false
반환합니다.
이 메소드는 ||
와 같이 동작합니다. 및 &&
연산자: fn
실제 값을 반환하면 arr.some()
즉시 true
반환하고 나머지 항목에 대한 반복을 중지합니다. fn
잘못된 값을 반환하면 arr.every()
즉시 false
반환하고 나머지 항목에 대한 반복도 중지합니다.
배열을 비교하기 위해 every
사용할 수 있습니다:
함수 arraysEqual(arr1, arr2) { return arr1.length === arr2.length && arr1.every((value, index) => value === arr2[index]); } 경고( arraysEqual([1, 2], [1, 2])); // 진실
arr.fill(value, start, end) – 인덱스 start
부터 end
까지 반복되는 value
으로 배열을 채웁니다.
arr.copyWithin(target, start, end) – start
위치에서 end
위치까지의 요소를 target
위치에 자체적 으로 복사합니다(기존 덮어쓰기).
arr.Flat(깊이)/arr.FlatMap(fn) 다차원 배열에서 새로운 평면 배열을 만듭니다.
전체 목록을 보려면 설명서를 참조하세요.
언뜻 보면 방법이 너무 많아 기억하기 어려울 수도 있습니다. 하지만 실제로는 그게 훨씬 쉽습니다.
치트 시트를 살펴보고 이를 알아보세요. 그런 다음 이 장의 작업을 해결하여 연습하여 배열 방법에 대한 경험을 쌓으세요.
나중에 배열을 사용하여 작업을 수행해야 하는데 방법을 모를 때마다 여기로 오셔서 치트 시트를 보고 올바른 방법을 찾으십시오. 예제는 올바르게 작성하는 데 도움이 됩니다. 곧 당신은 특별한 노력을 기울이지 않고도 방법을 자동으로 기억하게 될 것입니다.
중요도: 5
"my-short-string"과 같이 대시로 구분된 단어를 카멜 표기 "myShortString"으로 변경하는 함수 camelize(str)
를 작성하세요.
즉, 모든 대시를 제거하고 대시 뒤의 각 단어가 대문자가 됩니다.
예:
camelize("배경색") == '배경색상'; camelize("list-style-image") == 'listStyleImage'; camelize("-webkit-transition") == 'WebkitTransition';
PS 힌트: 문자열을 배열로 분할하고 변환한 후 다시 join
하려면 split
사용하세요.
테스트를 통해 샌드박스를 엽니다.
함수 카멜라이즈(str) { 문자열을 반환 .split('-') // 'my-long-word'를 배열 ['my', 'long', 'word']로 분할합니다. .지도( // 첫 번째 항목을 제외한 모든 배열 항목의 첫 글자를 대문자로 바꿉니다. // ['my', 'long', 'word']를 ['my', 'Long', 'Word']로 변환합니다. (단어, 색인) => 색인 == 0 ? 단어 : 단어[0].toUpperCase() + 단어.슬라이스(1) ) .가입하다(''); // ['my', 'Long', 'Word']를 'myLongWord'에 결합합니다. }
샌드박스에서 테스트를 통해 솔루션을 엽니다.
중요도: 4
arr
배열을 가져오고 a
보다 크거나 같고 b
보다 작거나 같은 값을 가진 요소를 찾고 결과를 배열로 반환하는 함수 filterRange(arr, a, b)
작성하세요.
함수는 배열을 수정해서는 안 됩니다. 새 배열을 반환해야 합니다.
예를 들어:
arr = [5, 3, 8, 1]로 설정합니다. 필터링 = filterRange(arr, 1, 4); 경고(필터링됨); // 3,1 (일치하는 값) 경고(arr); // 5,3,8,1 (수정되지 않음)
테스트를 통해 샌드박스를 엽니다.
함수 filterRange(arr, a, b) { // 더 나은 가독성을 위해 표현식 주위에 괄호를 추가했습니다. return arr.filter(item => (a <= 항목 && 항목 <= b)); } arr = [5, 3, 8, 1]로 설정합니다. 필터링 = filterRange(arr, 1, 4); 경고(필터링됨); // 3,1 (일치하는 값) 경고(arr); // 5,3,8,1 (수정되지 않음)
샌드박스에서 테스트를 통해 솔루션을 엽니다.
중요도: 4
배열 arr
가져와서 a
와 b
사이에 있는 값을 제외한 모든 값을 제거하는 함수 filterRangeInPlace(arr, a, b)
를 작성하세요. 테스트는 다음과 같습니다: a ≤ arr[i] ≤ b
.
함수는 배열만 수정해야 합니다. 아무것도 반환하면 안 됩니다.
예를 들어:
arr = [5, 3, 8, 1]로 설정합니다. filterRangeInPlace(arr, 1, 4); // 1부터 4까지를 제외한 숫자를 제거합니다. 경고(arr); // [3, 1]
테스트를 통해 샌드박스를 엽니다.
함수 filterRangeInPlace(arr, a, b) { for (let i = 0; i < arr.length; i++) { Val = arr[i]; // 간격을 벗어나면 제거 if (val < a || val > b) { arr.splice(i, 1); 나--; } } } arr = [5, 3, 8, 1]로 설정합니다. filterRangeInPlace(arr, 1, 4); // 1부터 4까지를 제외한 숫자를 제거합니다. 경고(arr); // [3, 1]
샌드박스에서 테스트를 통해 솔루션을 엽니다.
중요도: 4
arr = [5, 2, 1, -10, 8]로 설정합니다. // ... 내림차순으로 정렬하는 코드 경고(arr); // 8, 5, 2, 1, -10
arr = [5, 2, 1, -10, 8]로 설정합니다. arr.sort((a, b) => b - a); 경고(arr);
중요도: 5
문자열 arr
배열이 있습니다. 우리는 그것의 정렬된 복사본을 갖고 싶지만 arr
수정되지 않은 상태로 유지해야 합니다.
그러한 복사본을 반환하는 copySorted(arr)
함수를 만듭니다.
let arr = ["HTML", "JavaScript", "CSS"]; let sorted = copySorted(arr); 경고(정렬됨); // CSS, HTML, 자바스크립트 경고(arr); // HTML, JavaScript, CSS(변경사항 없음)
slice()
사용하여 복사본을 만들고 그에 대한 정렬을 실행할 수 있습니다.
함수 copySorted(arr) { return arr.slice().sort(); } let arr = ["HTML", "JavaScript", "CSS"]; let sorted = copySorted(arr); 경고(정렬됨); 경고(arr);
중요도: 5
"확장 가능한" 계산기 개체를 생성하는 생성자 함수 Calculator
만듭니다.
작업은 두 부분으로 구성됩니다.
먼저, "NUMBER 연산자 NUMBER"(공백으로 구분) 형식의 "1 + 2"
와 같은 문자열을 가져와 결과를 반환하는 calculate(str)
메서드를 구현합니다. 플러스 +
마이너스 -
이해해야 합니다.
사용 예:
calc = 새 계산기로 둡니다. 경고(calc.calculate("3 + 7") ); // 10
그런 다음 계산기에 새 작업을 가르치는 addMethod(name, func)
메서드를 추가합니다. 연산자 name
과 이를 구현하는 두 개의 인수 함수 func(a,b)
를 사용합니다.
예를 들어 곱셈 *
, 나눗셈 /
및 거듭제곱 **
을 추가해 보겠습니다.
powerCalc = 새 계산기로 설정합니다. powerCalc.addMethod("*", (a, b) => a * b); powerCalc.addMethod("/", (a, b) => a / b); powerCalc.addMethod("**", (a, b) => a ** b); 결과 = powerCalc.calculate("2 ** 3"); 경고(결과); // 8
이 작업에는 괄호나 복잡한 표현이 없습니다.
숫자와 연산자는 정확히 공백 하나로 구분됩니다.
추가하려는 경우 오류 처리가 발생할 수 있습니다.
테스트를 통해 샌드박스를 엽니다.
메소드가 어떻게 저장되는지 참고하세요. 간단히 this.methods
속성에 추가됩니다.
모든 테스트와 수치 변환은 calculate
메소드에서 수행됩니다. 앞으로는 더 복잡한 표현을 지원하도록 확장될 수 있습니다.
함수 계산기() { this.methods = { "-": (a, b) => a - b, "+": (a, b) => a + b }; this.calculate = 함수(str) { 분할 = str.split(' '), a = +분할[0], op = 분할[1], b = +분할[2]; if (!this.methods[op] || isNaN(a) || isNaN(b)) { NaN을 반환합니다. } return this.methods[op](a, b); }; this.addMethod = 함수(이름, func) { this.methods[이름] = func; }; }
샌드박스에서 테스트를 통해 솔루션을 엽니다.
중요도: 5
user
개체 배열이 있고 각 개체에는 user.name
있습니다. 이를 이름 배열로 변환하는 코드를 작성하세요.
예를 들어:
let john = { 이름: "John", 나이: 25 }; let pete = { 이름: "피트", 나이: 30 }; let mary = { 이름: "Mary", 나이: 28 }; 사용자 = [ 존, 피트, 메리 ]; let names = /* ... 귀하의 코드 */ 경고(이름); // 존, 피트, 메리
let john = { 이름: "John", 나이: 25 }; let pete = { 이름: "피트", 나이: 30 }; let mary = { 이름: "Mary", 나이: 28 }; 사용자 = [ 존, 피트, 메리 ]; let names = users.map(item => item.name); 경고(이름); // 존, 피트, 메리
중요도: 5
user
개체 배열이 있고 각 개체에는 name
, surname
및 id
있습니다.
id
및 fullName
있는 객체의 또 다른 배열을 생성하는 코드를 작성합니다. 여기서 fullName
name
및 surname
에서 생성됩니다.
예를 들어:
let john = { 이름: "John", 성: "Smith", ID: 1 }; let pete = { 이름: "피트", 성: "헌트", ID: 2 }; let mary = { 이름: "Mary", 성: "Key", ID: 3 }; 사용자 = [ 존, 피트, 메리 ]; let usersMapped = /* ... 귀하의 코드 ... */ /* usersMapped = [ { 전체 이름: "John Smith", ID: 1 }, { 전체 이름: "피트 헌트", ID: 2 }, { 전체 이름: "메리 키", ID: 3 } ] */ 경고( usersMapped[0].id ) // 1 경고( usersMapped[0].fullName ) // 존 스미스
따라서 실제로는 하나의 개체 배열을 다른 개체 배열에 매핑해야 합니다. 여기에서 =>
사용해 보세요. 작은 문제가 있습니다.
let john = { 이름: "John", 성: "Smith", ID: 1 }; let pete = { 이름: "피트", 성: "헌트", ID: 2 }; let mary = { 이름: "Mary", 성: "Key", ID: 3 }; 사용자 = [ 존, 피트, 메리 ]; usersMapped = users.map(사용자 => ({ 전체 이름: `${user.name} ${user.surname}`, 아이디 : user.id })); /* usersMapped = [ { 전체 이름: "John Smith", ID: 1 }, { 전체 이름: "피트 헌트", ID: 2 }, { 전체 이름: "메리 키", ID: 3 } ] */ 경고(userMapped[0].id ); // 1 경고( usersMapped[0].fullName ); // 존 스미스
화살표 기능에서는 추가 괄호를 사용해야 합니다.
우리는 다음과 같이 쓸 수 없습니다:
usersMapped = users.map(사용자 => { 전체 이름: `${user.name} ${user.surname}`, 아이디 : user.id });
우리가 기억하는 것처럼 두 개의 화살표 함수가 있습니다: 본문 value => expr
및 본문 value => {...}
.
여기서 JavaScript는 {
객체의 시작이 아닌 함수 본문의 시작으로 처리합니다. 해결 방법은 "일반" 대괄호로 묶는 것입니다.
usersMapped = users.map(사용자 => ({ 전체 이름: `${user.name} ${user.surname}`, 아이디 : user.id }));
이제 괜찮습니다.
중요도: 5
age
속성이 있는 객체의 배열을 가져와서 age
별로 정렬하는 함수 sortByAge(users)
를 작성하세요.
예를 들어:
let john = { 이름: "John", 나이: 25 }; let pete = { 이름: "피트", 나이: 30 }; let mary = { 이름: "Mary", 나이: 28 }; let arr = [피트, 존, 메리 ]; sortByAge(arr); // 지금: [존, 메리, 피트] 경고(arr[0].이름); // 존 경고(arr[1].name); // 메리 경고(arr[2].이름); // 피트
함수 sortByAge(arr) { arr.sort((a, b) => a.나이 - b.나이); } let john = { 이름: "John", 나이: 25 }; let pete = { 이름: "피트", 나이: 30 }; let mary = { 이름: "Mary", 나이: 28 }; let arr = [피트, 존, 메리 ]; sortByAge(arr); // 이제 정렬된 내용은 다음과 같습니다: [john, mary, pete] 경고(arr[0].이름); // 존 경고(arr[1].name); // 메리 경고(arr[2].이름); // 피트
중요도: 3
배열의 요소를 섞는(무작위로 재정렬하는) 함수 shuffle(array)
작성하세요.
shuffle
을 여러 번 실행하면 요소 순서가 달라질 수 있습니다. 예를 들어:
arr = [1, 2, 3]으로 설정합니다. 섞기(arr); // arr = [3, 2, 1] 섞기(arr); // arr = [2, 1, 3] 섞기(arr); // arr = [3, 1, 2] // ...
모든 요소 주문은 동일한 확률을 가져야 합니다. 예를 들어, [1,2,3]
각 경우의 동일한 확률로 [1,2,3]
또는 [1,3,2]
또는 [3,1,2]
등으로 재정렬될 수 있습니다.
간단한 해결책은 다음과 같습니다.
함수 셔플(배열) { array.sort(() => Math.random() - 0.5); } arr = [1, 2, 3]으로 설정합니다. 섞기(arr); 경고(arr);
Math.random() - 0.5
양수 또는 음수일 수 있는 난수이므로 정렬 함수는 요소를 무작위로 재정렬하므로 어느 정도 작동합니다.
그러나 정렬 기능은 이런 방식으로 사용되도록 의도된 것이 아니기 때문에 모든 순열이 동일한 확률을 갖는 것은 아닙니다.
예를 들어 아래 코드를 살펴보세요. shuffle
1000000번 실행하고 가능한 모든 결과의 출현 횟수를 계산합니다.
함수 셔플(배열) { array.sort(() => Math.random() - 0.5); } // 가능한 모든 순열의 출현 횟수 개수 = { '123': 0, '132': 0, '213': 0, '231': 0, '321': 0, '312': 0 }; for (let i = 0; i < 1000000; i++) { 배열 = [1, 2, 3]; 셔플(배열); 개수[array.join('')]++; } // 가능한 모든 순열의 개수를 표시합니다. for (키를 세도록 놔두세요) { Alert(`${key}: ${count[key]}`); }
예제 결과(JS 엔진에 따라 다름):
123: 250706 132: 124425 213: 249618 231: 124880 312: 125148 321: 125223
우리는 편견을 명확하게 볼 수 있습니다. 123
과 213
다른 사람들보다 훨씬 자주 나타납니다.
코드의 결과는 JavaScript 엔진마다 다를 수 있지만 이미 접근 방식이 신뢰할 수 없음을 알 수 있습니다.
왜 작동하지 않습니까? 일반적으로 sort
"블랙 박스"입니다. 배열과 비교 함수를 던지고 배열이 정렬 될 것으로 예상합니다. 그러나 비교의 무작위성으로 인해 블랙 박스는 화를 내며, 정확히 어떻게 미친지는 엔진간에 다른 콘크리트 구현에 달려 있습니다.
작업을 수행하는 다른 좋은 방법이 있습니다. 예를 들어, Fisher-Yates Shuffle이라는 훌륭한 알고리즘이 있습니다. 아이디어는 배열을 역 순서로 걸어 가서 각 요소를 임의의 요소로 바꾸는 것입니다.
함수 셔플 (배열) { for (i = array.length-1; i> 0; i--) { j = math.floor (math.random () * (i + 1)); // 0에서 i의 임의의 인덱스 // 요소 배열 [i] 및 배열 [j] // 우리는이를 달성하기 위해 "파괴 할당"구문을 사용합니다 // 이후 챕터에서 해당 구문에 대한 자세한 내용은 찾을 수 있습니다. // 동일은 다음과 같이 쓸 수 있습니다. // t = 배열 [i]; 배열 [i] = 배열 [j]; 배열 [j] = t [배열 [i], 배열 [j]] = [배열 [j], 배열 [i]]; } }
같은 방식으로 테스트합시다.
함수 셔플 (배열) { for (i = array.length-1; i> 0; i--) { j = math.floor (math.random () * (i + 1)); [배열 [i], 배열 [j]] = [배열 [j], 배열 [i]]; } } // 가능한 모든 순열에 대한 외관 수 count = { '123': 0, '132': 0, '213': 0, '231': 0, '321': 0, '312': 0 }; for (i = 0; i <10000000; i ++) { 배열 = [1, 2, 3]; 셔플 (배열); count [array.join ( '')] ++; } // 가능한 모든 순열의 수를 표시합니다 for (count in count) { alert (`$ {key} : $ {count [key]}`); }
예제 출력 :
123 : 166693 132 : 166647 213 : 166628 231 : 167517 312 : 166199 321 : 166316
지금은 좋아 보인다 : 모든 순열은 같은 확률로 나타납니다.
또한 Fisher-Yates 알고리즘이 훨씬 좋으며 "정렬"오버 헤드가 없습니다.
중요도: 4
속성 age
의 객체 배열을 가져오고 평균 연령을 반환 getAverageAge(users)
기능을 작성하십시오.
평균의 공식은 (age1 + age2 + ... + ageN) / N
입니다.
예를 들어:
John = {이름 : "John", Age : 25}; Pete = {이름 : "Pete", Age : 30}하자; Mary = {이름 : "Mary", 나이 : 29}; arr = [John, Pete, Mary]; 경고 (getaverageage (arr)); // (25 + 30 + 29) / 3 = 28
기능 getaverageage (사용자) { return users.reduce ((prev, user) => prev + user.age, 0) / user.length; } John = {이름 : "John", Age : 25}; Pete = {이름 : "Pete", Age : 30}하자; Mary = {이름 : "Mary", 나이 : 29}; arr = [John, Pete, Mary]; 경고 (getaverageage (arr)); // 28
중요도: 4
arr
배열로 둡니다.
arr
의 고유 항목이 있는 배열을 반환해야 하는 함수 unique(arr)
를 만듭니다.
예를 들어:
함수 고유(arr) { /* 귀하의 코드 */ } 문자열 = [ "Hare", "Krishna", "Hare", "Krishna", "크리슈나", "크리슈나", "토끼", "토끼", ":-O" ]; 경고 (고유 한 (문자열)); // 토끼, 크리슈나, :-O
테스트를 통해 샌드박스를 엽니다.
배열 항목을 걸어 보자 :
각 항목에 대해 결과 배열에 이미 해당 항목이 있는지 확인합니다.
그렇다면 그렇다면 무시하십시오. 그렇지 않으면 결과를 추가하십시오.
함수 고유(arr) { 결과 = []; for (het str of arr) { if (! result.includes (str)) { result.push (str); } } 반환 결과; } 문자열 = [ "Hare", "Krishna", "Hare", "Krishna", "크리슈나", "크리슈나", "토끼", "토끼", ":-O" ]; 경고 (고유 한 (문자열)); // 토끼, 크리슈나, :-O
코드는 작동하지만 잠재적 인 성능 문제가 있습니다.
Method result.includes(str)
내부적으로 배열 result
걸고 각 요소를 str
과 비교하여 일치를 찾습니다.
따라서 result
에 100
요소가 있고 아무도 str
일치하지 않으면 전체 result
걷고 정확히 100
비교를합니다. 그리고 result
10000
과 마찬가지로 큰 경우 10000
비교가있을 것입니다.
JavaScript 엔진이 매우 빠르기 때문에 그 자체로는 문제가되지 않으므로 10000
배열은 마이크로 초의 문제입니다.
그러나 우리는 for
루프에서 arr
의 각 요소에 대해 그러한 테스트를 수행합니다.
따라서 arr.length
10000
인 경우 10000*10000
= 100 millions 비교와 같은 것이 있습니다. 그것은 많은 것입니다.
따라서 솔루션은 작은 배열에만 적합합니다.
또한 챕터 맵과 설정에서 최적화하는 방법을 볼 수 있습니다.
샌드박스에서 테스트를 통해 솔루션을 엽니다.
중요도: 4
{id:..., name:..., age:... }
형식의 사용자 배열을 받았다고 가정 해 봅시다.
ID로부터 객체를 키우고 id
키로 만들고 항목을 값으로 만들어내는 groupById(arr)
를 만듭니다.
예를 들어:
사용자 = [ {id : 'John', 이름 : "John Smith", 나이 : 20}, {id : 'Ann', 이름 : "Ann Smith", 나이 : 24}, {id : 'Pete', 이름 : "Pete Peterson", 나이 : 31}, ]; usersById = groupById (사용자); /* // 통화 후 우리는 다음을해야합니다. userSyId = { John : {id : 'John', 이름 : "John Smith", Age : 20}, 앤 : {id : 'ann', 이름 : "앤 스미스", 나이 : 24}, Pete : {id : 'Pete', 이름 : "Pete Peterson", Age : 31}, } */
이러한 기능은 서버 데이터로 작업 할 때 실제로 편리합니다.
이 작업에서 우리는 id
독특하다고 가정합니다. 동일한 id
있는 두 개의 배열 항목이 없을 수 있습니다.
솔루션에서 배열 .reduce
메소드를 사용하십시오.
테스트를 통해 샌드박스를 엽니다.
함수 groupById (배열) { return array.reduce ((obj, value) => { obj [value.id] = value; 반환 obj; }, {}) }
샌드박스에서 테스트를 통해 솔루션을 엽니다.