23.12.01.(FRI).TIL.
Part.03 배열과 반복문
배열
배열 : 순서가 있는 컬렉션을 저장할 때 쓰는 자료구조
배열 선언
아래 두 문법을 사용하면 빈 배열을 만들 수 있다.
let arr = new Array();
let arr = [];
pop-push와 shift-unshift
큐(queue)는 배열을 사용해 만들 수 있는 대표적인 자료구조로, 배열과 마찬가지로 순서가 있는 컬렉션을 저장하는 데 사요된다.
- push : 맨 끝에 요소를 추가한다.
- shift : 제일 앞 요소를 꺼내 제거한 후 남아있는 요소를 앞으로 밀어준다. 이렇게 하면 두 번째 요소가 첫 번째 요소가 된다.
스택(stack)
- push : 요소를 스택 끝에 집어넣는다.
- pop : 스택 끝 요소를 추출한다.
배열 끝에 무언가를 해주는 메서드
pop : 배열 끝 요소를 제거하고, 제거한 요소를 반환
push : 배열 끝에 요소를 추가
배열 앞에 무언가를 해주는 메서드
shift : 배열 앞 요소를 제거하고, 제거한 요소를 반환한다.
unshift : 배열 앞에 요소를 추가한다.
배열의 내부 동작 원리
배열의 본질은 객체이다. 배열은 원시 자료형이 아닌 객체형에 속하기 때문에 객체처럼 동작한다.
성능
push와 pop은 빠르지만 shift와 unshift는 느리다.
반복문
배열에 적용할 수 있는 또 다른 순회 문법으론 for .. of가 있다.
let fruits = ["사과", "오렌지", "자두"];
// 배열 요소를 대상으로 반복 작업을 수행한다.
for (let fruit of fruits) {
alert( fruit );
}
for .. of 를 사용하면 현재 요소의 인덱스는 얻을 수 없고 값만 얻을 수 있다.
배열은 객체형에 속하므로 for .. in을 사용하는 것도 가능하다.
let arr = ["사과", "오렌지", "배"];
for (let key in arr) {
alert( arr[key] );
}
'length' 프로퍼티
배열에 무언가 조작을 가하면 length 프로퍼티가 자동으로 갱신된다. length 프로퍼티는 배열 내 요소의 개수가 아니라 가장 큰 인덱스에 1을 더한 값이다.
new Array()
new Array(number)를 이용해 만든 배열의 요소는 모두 undefined이다.
이런 뜻밖의 상황을 마주치지 않기 위해 new Array의 기능을 잘 알지 않는 한 대부분의 개발자가 대괄호를 써서 배열을 만든다.
다차원 배열
배열 역시 배열의 요소가 될 수 있다. 이런 배열을 가리켜 다차원 배열(multidimensional array)이라 부른다. 다차원 배열은 행렬을 저장하는 용도로 쓰인다.
toString
배열엔 toString 메서드가 구현되어 있어 이를 호출하면 요소를 쉼표로 구분한 문자열이 반환된다.
배열과 메서드
요소 추가-제거 메서드
- arr.push(...items) : 맨 끝에 요소 추가
- arr.pop() : 맨 끝 요소 제거
- arr.shift() : 맨 앞 요소 제거
- arr.unshift(...items) : 맨 앞에 요소 추가
splice
arr.splice(start)는 만능 스위스 맥가이버 칼 같은 메서드이다. 요소를 자유자재로 다룰 수 있게 해준다. 이 메서드를 사용하면 요소 추가, 삭제, 교체가 모두 가능하다.
arr.splice(index[, deleteCount, elem1, ... , elemN])
첫 번째 매개변수는 조작을 가할 첫 번째 요소를 가리키는 인덱스(index)이다. 두 번째 매개변수는 deleteCount로, 제거하고자 하는 요소의 개수를 나타낸다. elem1, ... , elemN은 배열에 추가할 요소를 나타낸다.
slice
arr.slice는 arr.splice와 유사해 보이지만 훨씬 간단하다.
arr.slice([start], [end])
이 메서드는 "start" 인덱스부터 ("end"를 제외한) "end" 인덱스까지의 요소를 복사한 새로운 배열을 반환한다.
concat
arr.concat은 기존 배열의 요소를 사용해 새로운 배열을 만들거나 기존 배열에 요소를 추가하고자 할 때 사용할 수 있다.
arr.concat(arg1, arg2 ... )
forEach로 반복작업 하기
arr.forEach는 주어진 함수를 배열 요소 각각에 대해 실행할 수 있게 해준다.
arr.forEach(function(item, index, array) {
// 요소에 무언가를 할 수 있다.
})
배열 탐색하기
indexOf, lastIndexOf와 includes
- arr.indexOf(item, from)는 인덱스 from부터 시작해 item(요소)을 찾는다. 요소를 발견하면 해당 요소의 인덱스를 반환하고, 발견하지 못했으면 -1을 반환한다.
- arr.lastIndexOf(item, from)는 위 메서드와 동일한 기능을 하는데, 검색을 끝에서부터 시작한다는 점만 다르다.
- arr.includes(item, from)는 인덱스 from부터 시작해 item이 있는지를 검색하는데, 해당하는 요소를 발견하면 true를 반환한다.
let arr = [1, 0, false];
alert( arr.indexOf(0) ); // 1
alert( arr.indexOf(false) ); // 2
alert( arr.indexOf(null) ); // -1
alert( arr.includes(1) ); // true
find와 findIndex
객체로 이루어진 배열이 있다고 가정해보자. 특정 조건에 부합하는 객체를 배열 내에서 어떻게 찾을 수 있을까?
let result = arr.find(function(item, index, array) {
// true가 반환되면 반복이 멈추고 해당 요소를 반환한다.
// 조건에 해당하는 요소가 없으면 undefined를 반환한다.
});
요소 전체를 대상으로 함수가 순차적으로 호출된다.
- item : 함수를 호출할 요소
- index : 요소의 인덱스
- array : 배열 자기 자신
filter
find 메서드는 함수의 반환 값을 true로 만드는 단 하나의 요소를 찾는다.
조건을 충족하는 요소가 여러 개라면 arr.filter(fn)을 사용하면 된다.
let results = arr.filter(function(item, index, array) {
// 조건을 충족하는 요소는 results에 순차적으로 더해진다.
// 조건을 충족하는 요소가 하나도 없으면 빈 배열이 반환된다.
})
배열을 변형하는 메서드
- map
map은 배열 요소 전체를 대상으로 함수를 호출하고, 함수 호출 결과를 배열로 반환해준다.
let result = arr.map(function(item, index, array) {
// 요소 대신 새로운 값을 반환한다.
})
- sort(fn)
arr.sort()는 배열의 요소를 정렬해준다. 배열 자체가 변경된다.
요소는 문자열로 취급되어 재정렬된다.
- reverse
arr.reverse는 arr의 요소를 역순으로 정렬시켜주는 메서드이다.
- split과 join
str.split(delim)는 구분자(delimiter) delim을 기준으로 문자열을 쪼개준다.
let names = 'Bilbo, Gandalf, Nazgul';
let arr = names.split(', ');
for (let name of arr) {
alert(`${name}에게 보내는 메시지`); // Bilbo에게 보내는 메시지
}
문자열을 글자 단위로 분리하기
split(s)의 s를 빈 문자열로 지정하면 문자열을 글자 단위로 분리할 수 있다.
let str = "test";
alert( str.split('') ); // t,e,s,t
arr.join(glue)은 split과 반대 역할을 하는 메서드이다. 인수 glue를 접착제처럼 사용해 배열 요소를 모두 합친 후 하나의 문자열을 만들어준다.
let arr = ['Bilbo', 'Gandalf', 'Nazgul'];
let str == arr.join(';'); // 배열 요소 모두를 ;를 사용해 하나의 문자열로 합친다.
alert( str ); // Bilbo; Gandalf; Nazgul
- reduce와 reduceRight
forEach, for, for .. of 를 사용하면 배열 내 요소를 대상으로 반복 작업을 할 수 있다.
reduce와 reduceRight는 배열을 기반으로 값 하나를 도출할 때 사용된다.
let value = arr.reduce(function(accumulator, item, index, array) {
// ...
}, [initial]);
- accumulator : 이전 함수 호출의 결과. initial은 함수 최초 호출 시 사용되는 초깃값을 나타냄(옵션)
- item : 현재 배열 요소
- index : 요소의 위치
- array : 배열
Array.isArray로 배열 여부 알아내기
자바스크립트에서 배열은 독립된 자료형으로 취급되지 않고 객체형에 속한다. 따라서 typeof로는 일반 객체와 배열을 구분할 수 없다.
Array.isArray(value)는 이럴 때 사용할 수 있는 유용한 메서드이다. value가 배열이라면 true를, 배열이 아니라면 false를 반환해준다.
alert(Array.isArray({})); // false
alert(Array.isArray([])); // true
배열 메서드와 'thisArg'
함수를 호출하는 대부분의 배열 메서드(find, filter, map 등. sort는 제외)는 thisArg라는 매개변수를 옵션으로 받을 수 있다.
thisARg는 아래와 같이 활용할 수 있다.
arr.find(func, thisArg);
arr.filter(func, thisArg);
arr.map(func, thisArg);
// ...
// thisArg는 선택적으로 사용할 수 있는 마지막 인수이다.
thisArg는 func의 this가 된다.
반복문
'while' 반복문
while (condition) {
// 코드
// '반복문 본문(body)'이라 불림
}
'do...while' 반복문
do {
// 반복문 본문
} while (condition);
이때 본문이 먼저 실행되고, 조건을 확인한 후 조건이 truthy인 동안엔 본문이 계속 실행된다.
do..wihle 문법은 조건이 truthy인지 아닌지에 상관없이, 본문을 최소한 한 번이라도 실행하고 싶을 때만 사용해야 한다.
'for' 반복문
for (begin; condition; step) {
// ... 반복문 본문 ...
}
for (let i = 0; i < 3 ; i++){
alert(i);
}
반복문 빠져나오기
let sum = 0;
while (true) {
let value = +prompt("숫자를 입력하세요.", '');
if(!value) break; // (*)
sum += value;
}
alert( '합계 : ' + sum );
다음 반복으로 넘어가기
for (let i = 0 ; i < 10; i++){
// 조건이 참이라면 남아있는 본문은 실행되지 않는다.
if (i % 2 == 0) continue;
alert(i); // 1, 3, 5, 7, 9가 차례대로 출력됨
}
break/continue와 레이블
레이블(label)은 반복문 앞에 콜론과 함께 쓰이는 식별자이다.
labelName: for (...) {
...
}
반복문 안에서 break <labelName> 문을 사용하면 레이블에 해당하는 반복문을 빠져나올 수 있다.
outer: for (let i = 0; i < 3; i++){
for (let j = 0; j < 3 ; j++){
let input = prompt(`${i},${j}의 값`, '');
// 사용자가 아무것도 입력하지 않거나 Cancel 버튼을 누르면 두 반복문 모두를 빠져나옵니다.
if (!input) break outer; // (*)
}
}
alert('완료!');
레이블을 별도의 줄에 써주는 것도 가능하다.
outer:
for (let i = 0 ; i < 3 ; i++) { ... }
break label; // 아래 for문으로 점프할 수 없다.
label: for (...)
break와 continue는 반복문 안에서만 사용할 수 있고, 레이블은 반드시 break이나 continue 지시자 위에 있어야 한다.
Part.03 배열과 반복문
함수
함수는 프로그램을 구성하는 주요 '구성 요소(building block)'이다. 함수를 이용하면 중복 없이 유사한 동작을 하는 코드를 여러 번 호출할 수 있다.
함수 선언
function showMessage() {
alert('안녕하세요!');
}
function name(param1, param2, ... , paramN) {
// 함수 본문
}
지역 변수
함수 내에서 선언한 변수인 지역 변수(local variable)는 함수 안에서만 접근할 수 있다.
외부 변수
함수 내부에서 함수 외부의 변수인 외부 변수(outer variable)에 접근할 수 있다.
매개변수
매개변수(parameter)를 이용하면 임의의 데이터를 함수 안에 전달할 수 있다. 매개변수는 인자(parameter)라고 불리기도 한다.
* 매개변수는 함수 선언 방식 괄호 사이에 있는 변수이다. (선언 시 쓰이는 용어).
* 인수는 함수를 호출할 때 매개변수에 전달되는 값이다. (호출 시 쓰이는 용어).
즉, 함수 선언 시 매개변수를 나열하게 되고, 함수를 호출할 땐 인수를 전달해 호출한다.
기본값
함수 호출 시 매개변수에 인수를 전달하지 않으면 그 값은 undefined가 된다.
매개변수 기본값 평가 시점
: 자바스크립트에선 함수를 호출할 때마다 매개변수 기본값을 평가한다. 물론 해당하는 매개변수가 없을 때만 기본값을 평가한다.
매개변수 기본값을 설정할 수 있는 또 다른 방법
: 가끔은 함수를 선언할 때가 아닌 함수 선언 후에 매개변수 기본값을 설정하는 것이 적절한 경우도 있다.
: 이런 경우엔 함수를 호출할 때 매개변수를 undefined와 비교하여 매개변수가 전달되었는지를 확인한다.
반환 값
함수를 호출했을 때 함수를 호출한 그곳에 특정 값을 반환하게 할 수 있다. 이때 이 특정 값을 반환 값(return value)이라고 부른다.
함수 이름짓기
"show"로 시작하는 함수는 대개 무언가를 보여주는 함수이다.
- "get..." : 값을 반환함
- "calc..." : 무언가를 계산함
- "create..." : 무언가를 생성함
- "check..." : 무언가를 확인하고 불린값을 반환함
함수 == 주석
함수는 간결하고, 한 가지 기능만 수행할 수 있게 만들어야 한다.
함수를 간결하게 만들면 테스트와 디버깅이 쉬워진다. 그리고 함수 그 자체로 주석의 역할까지 한다!
함수 표현식
자바스크립트는 함수를 특별한 종류의 값으로 취급한다. 다른 언어에서처럼 "특별한 동작을 하는 구조"로 취급되지 않는다.
콜백 함수
function ask(question, yes, no){
if (confirm(question)) yes()
else no();
}
function showOk() {
alert( "동의하셨습니다. ");
}
function showCancel() {
alert( "취소 버튼을 누르셨습니다." );
}
// 사용법 : 함수 showOk와 showCancel가 ask의 함수의 인수로 전달됨
ask("동의하십니까?", showOk, showCancel);
함수 ask의 인수, showOk와 showCancel은 콜백 함수 또는 콜백이라고 불린다.
함수를 함수의 인수로 전달하고, 필요하다면 인수로 전달한 그 함수를 "나중에 호출(called back)"하는 것이 콜백 함수의 개념이다. 위 예시에선 사용자가 "yess"라고 대답한 경우 showOk가 콜백이 되고, "no"라고 대답한 경우 showCancel가 콜백이 된다.
함수는 "동작"을 나타내는 값이다.
문자열이나 숫자 등은 일반적인 값들은 데이터를 나타낸다.
함수는 하나의 *동작(action)*을 나타낸다.
동작을 대변하는 값인 함수를 변수 간 전달하고, 동작이 필요할 때 이 값을 실행할 수 있다.
함수 표현식 vs 함수 선언문
- 함수 선언문 : 함수는 주요 코드 흐름 중간에 독자적인 구문 형태로 존재한다.
// 함수 선언문
function sum(a, b){
return a + b;
}
- 함수 표현식 : 함수는 표현식이나 구문 구성 (syntax construct) 내부에 생성된다. 아래 예시에선 함수가 할당 연산자 =를 이용해 만든 "할당 표현식" 우측에 생성되었다.
// 함수 표현식
let sum = function(a, b) {
return a + b;
}
함수 표현식은 실제 실행 흐름이 해당 함수에 도달했을 때 함수를 생성한다. 따라서 실행 흐름이 함수에 도달했을 때부터 해당 함수를 사용할 수 있다.
함수 선언문은 함수 선언문이 정의되기 전에도 호출할 수 있다.
엄격 모드에서 함수 선언문이 코드 블록 내에 위치하면 해당 함수는 블록 내 어디서든 접근할 수 있다. 하지만 블록 밖에서는 함수에 접근하지 못한다.
화살표 함수 기본
let function = (arg1, arg2, ... argN) => expression
let func = function(arg1, arg2, ...argN) {
return expression;
}
본문이 여러 줄인 화살표 함수
let sum = (a, b) => { // 중괄호는 본문 여러 줄로 구성되어 있음을 알려줌.
let result = a + b;
return result; // 중괄호를 사용했다면, return 지시자로 결괏값을 반환해주어야 한다.
}
alert( sum(1, 2) ); // 3
나머지 매개변수와 스프레드 문법
나머지 매개변수 ...
함수 정의 방법과 상관없이 함수에 넘겨주는 인수의 개수엔 제약이 없다.
function sum(a, b){
return a + b;
}
alert( sum(1, 2, 3, 4, 5,) );
함수를 정의할 땐 인수를 두 개만 받게 하고, 실제 함수를 호출할 땐 이보다 더 많은 '여분의' 인수를 전달했지만, 에러가 발생하지 않았다. 다만 반환 값은 처음 두 개의 인수만을 사용해 계산된다.
arguments 객체
유사 배열 객체(array-like object)인 arguments를 사용하면 인덱스를 사용해 인수에 접근할 수 있다.
스프레드 문법
let arr = [3, 5, 1];
alert( Math.max(arr) ); // NaN
--
let arr = [3, 5, 1];
alert( Math.max(...arr) ); // 5 (스프레드 문법이 배열을 인수 목록으로 바꿔주었다.)
배열과 객체의 복사본 만들기
Object.assign() 말고도 스프레드 문법을 사용하면 배열과 객체를 복사할 수 있다.
let arr = [1, 2, 3];
let arrCopy = [...arr];
// 배열을 펼처서 각 요소를 분리 후, 매개변수 목록으로 만든 다음에 매개변수 목록을 새로운 배열에 할당
// 배열 복사본의 요소가 기존 배열 요소와 진짜 같을까?
alert(JSON.stringify(arr) === JSON.stringify(arrCopy)); // true
// 두 배열은 같을까?
alert(arr === arrCopy); // false (참조가 다름)
// 참조가 다르므로 기존 배열을 수정해도 복사본은 영향을 받지 않는다.
arr.push(4);
alert(arr); // 1, 2, 3, 4
alert(arrCopy); // 1, 2, 3
--
let obj = { a: 1, b: 2, c: 3 };
let objCopy = { ...obj };
// 객체를 펼쳐서 각 요소를 분리 후, 매개변수 목록으로 만든 다음에 매개변수 목록을 새로운 객체에 할당함
// 객체 복사본의 프로퍼티들이 기존 객체의 프로퍼티들과 진짜 같을까?
alert(JSON.stringify(obj) === JSON.stringify(objCopy)); // true
// 두 객체는 같을까?
alert(obj === objCopy); // false (참조가 다름)
// 참조가 다르므로 기존 객체를 수정해도 복사본은 영향을 받지 않는다.
obj.d = 4;
alert(JSON.stringify(obj)); // {"a":1,"b":2,"c":3,"d":4}
alert(JSON.stringify(objCopy)); // {"a":1,"b":2,"c":3}
* 출처 : 내배캠 깃북
'Coding > TIL' 카테고리의 다른 글
TIL | #05 | 자바스크립트 기초 | 23.12.03.(일) (1) | 2023.12.03 |
---|---|
TIL | #04 | 자바스크립트 기초 | 23.12.02.(토) (1) | 2023.12.03 |
TIL | #02 | 자바스크립트 기초 | 23.11.30.(목) (0) | 2023.12.01 |
TIL | #01 | 자바스크립트 기초 | 23.11.29.(수) (1) | 2023.11.29 |
TIL | #00 | TIL 기록 시작합니다. | 23.11.29.(수) (0) | 2023.11.29 |