js에서 sort()메소드를 사용하면 배열을 정렬할 수 있다. sort는 정렬한 배열을 리턴해주는데 주의할 점은 정렬한 배열은 새 배열이 아니라 원본 배열과 같은 녀석이다(즉 같은 참조이다).

 

sort()메소드에 아무런 인자도 전달해주지 않으면 기본적으로 유니코드에 정의된 문자열 순서에 따라 정렬해준다.

즉,

const letters = ['A', 'C', 'E', 'B'];
const nums = [111, 13, 20, 10000];

letters.sort();
nums.sort();

console.log(letters); // ['A', 'B', 'C', 'E'];
console.log(nums);    // [10000, 111, 13, 20]

숫자들조차도 문자들 정렬할 때처럼 사전순으로 정렬된 모습이다ㅋㅋ 즉 문자열을 정렬할 경우엔 그냥 sort()를 써도 되지만, 숫자들을 정렬할 때는 sort()만 한다고 되지 않는 모습. 파이썬은 그냥 해주던데..에휴

 

암튼 이렇게 숫자를 정렬하고 싶은 상황 등에선 sort()에 콜백함수를 전달해야 한다. 

const nums = [111, 13, 20, 10000];

nums.sort((a, b) => a - b); // 오름차순 정렬
console.log(nums);          // [13, 20, 111, 10000]

nums.sort((a, b) => b - a); // 내림차순 정렬
console.log(nums);          // [10000, 111, 20, 13]

급하면 여기까지만 보고 나가도 됨.

근데 이제 이 이유가 궁금한 사람들이 있잖아? 나처럼. 

다른 데 가지 말고 여기서 저렇게 해야 하는 이유를 같이 보자구요 :) ㅋㅋㅋㅋㅋㅋ

 

우선, sort()는 파라미터로 compareFunction을 옵셔널로 받음. 옵셔널이란 말은 이 놈을 받을 수도 있고 안 받을 수도 있다는 얘긴데 받는다면 이 compareFunction을 기준으로 정렬이 되고, 안 받는다면 유니코드에 의한 문자열 순서대로 정렬한다는 것.

 

암튼 이 compareFunction은 파라미터를 두 개 받도록 만들어야 함. (a, b)로 받는다고 해봅시다. 그러면 이 함수의 리턴값에 의해 어떻게 정렬할지가 결정되는데, 그건 다음과 같음.

 

1. 리턴값이 음수 : a가 앞으로 오도록 정렬

2. 리턴값이 0 : a, b를 바꾸지 않음

3. 리턴값이 양수 :  b가 앞으로 오도록 정렬

 

따라서 리턴값을 a - b로 하면 오름차순으로, b - a로 하면 내림차순으로 정렬할 수 있는 것임!

 

※ 참고링크

https://developer.mozilla.org/ko/docs/Web/JavaScript/Reference/Global_Objects/Array/sort

 

Array.prototype.sort() - JavaScript | MDN

sort() 메서드는 배열의 요소를 적절한 위치에 정렬한 후 그 배열을 반환합니다. 정렬은 stable sort가 아닐 수 있습니다. 기본 정렬 순서는 문자열의 유니코드 코드 포인트를 따릅니다.

developer.mozilla.org

 

일반적인 화살표 함수의 사용법은 다음과 같다.

그러나 여기서 반환값이 한 줄로 표현가능하면 return과 중괄호를 생략가능! 즉 다음처럼 쓸 수 있다.

그러나 리턴값이 객체(Object)이면, 저렇게 중괄호와 return을 모두 생략한 형태로 작성하면 error가 난다. 소괄호를 감싸줘야 한다. 즉 다음처럼 써야 함.

중괄호를 그대로 쓰면서 return을 생략 가능한 줄 알았는데 아니었다. 다시는 이 사실을 잊지 말고자 기록.

 

정리

여러 줄이면 중괄호를 쓰고, return을 써야 한다.

내용이 return문 한 줄이면 중괄호와 return 생략 가능, 그러나 return되는 것이 '객체'라면 소괄호로 감쌀 것(객체임을 명시적으로 알려주는 역할을 한다)

기존에 배열에서 for loop를 돌 때 사용가능한 방법으로 알고 있던 것은 for-of문을 사용하는 것이었다.

그러나 js에선 기본적으로 배열에서 루프를 도는 것고 관련해  forEach와 map이란 메소드를 제공한다. 이들에 대해 간단하게 살펴보자.

 

1. forEach

파라미터로 콜백함수를 작성하며, 이 콜백함수의 파라미터로 배열의 각각 요소들이 들어가서 콜백함수의 내용을 수행한다. 즉 콜백함수에는 파라미터 하나가 반드시 작성되어야 한다.

당연히 화살표 함수(Arrow function)으로도 작성가능

근데 이 콜백함수에 작성하는 파라미터를 여러 개 쓸 수도 있다. 일단 첫 번째 파라미터는 배열의 각각의 요소들이 들어가는 자리고, 두 번째 파라미터를 주면 요소의 인덱스를 관리할 수 있게 된다. 당연히 이 녀석은 처음엔 0부터 시작해서 각 요소들이 순회될 때마다 1씩 더해지는 값이다. 주로 다음과 같이 많이 쓴다.

세 번째 파라미터는 주로 arr이란 이름으로 많이들 작성하며, forEach메소드를 쓰고 있는 배열 자체(위 예시에선 myArr이란 배열)이 arr로 들어온다. myArr처럼 변수이름에 담아서 배열을 쓸 경우엔 굳이 쓸 필요 없긴 하지만, [1, 2, 3, 4]처럼 리터럴 배열을 사용할 경우엔 요긴하게 쓸 수 있을 것이다.

 

2. map

forEach와 동작하는 방식은 거의 비슷하다. 파라미터로 콜백함수를 받으며, 콜백함수의 첫 번째 파라미터로는 배열의 각각 요소들이, 두 번째 파라미터로는 인덱스 값이 전달된다. 그러나 map이 forEach와 다른 점은 메소드의 호출 결과로 또 다른 배열을 리턴한다는 것이다(forEach메소드는 리턴값이 없다). 즉 콜백함수 내에서 return문을 작성하게 되면 각각의 리턴값으로 구성된 새로운 배열이 map메소드의 결과로 리턴된다는 것이다!

 

즉 단순 반복작업이 필요하면 forEach, 새로운 배열이 필요하면 map메소드를 사용한다는 것.

주의할 점이 있는데, 두 메소드의 최대 반복 횟수는 메소드를 처음 호출할 때의 요소 개수이다. 즉 중간에 배열의 길이가 늘어나도 처음의 배열 원소 개수만큼만 동작한다는 점. 그러나 형광펜으로 강조했듯이 최대 반복 횟수가 처음 호출할 때의 요소 개수란 것이지 언제나 반복 횟수가 그렇다는 게 아니다. 배열의 길이가 줄어들면(pop을 한다던지), 그 만큼 반복횟수가 줄어든다. 이 점 알아두고 사용하도록 하자.

 

자바스크립트에서도 다른 언어와 마찬가지로 && (and의 의미)와 || (or의 의미)라는 비교연산자가 있다. 그러나 다른 언어에서는 이들이 단순히 true 또는  false의 값만 리턴하는 것과 다르게, JS에선 이를 변수 할당에 이용할 수 있다. 단순히 bool 타입의 변수 할당이 아닌 다른 값(예를 들면 문자열)등을 할당할 때도 이들을  활용 가능하며, 상당히 직관적이다.

 

// sample
let ex0 = 1234;
let ex1 = false;

let ex2 = ex0 || 100;  // ex2 = 1234
let ex3 = ex1 || 100;  // ex3 = 100;

사실 공부중에 이렇게 할 수 있다는 걸 알게 됐는데, 처음엔 "어떤 의미인지는 대충 알겠는데 이게 돼?" 였다. 지금까지 나는 이런 상황에선 3항 연산자를 사용해서 또는 if문을 활용해서 할당해왔기 때문. 정리하자면 ||는 피연산자를 리턴할 수 있는데(bool타입이 아닌 피연산자도 리턴가능하다!!), 첫 번째 피연산자가 거짓이면 두 번째 피연산자의 값을 리턴하고 그렇지 않으면 첫 번째 피연산자를 리턴한다고 한다. 즉 첫 피연산자가 참으로 평가되면 첫 피연산자를, 첫 피연산자가 거짓으로 평가되면 두 번째 피연산자를 리턴한다는 것! 이 때 '거짓'으로 평가되는 것은 직접적으로 bool타입의 false 뿐만 아니라 빈 배열([]), 빈 문자열(''), 0, null, undefined, NaN 등이 있다.

 

이 녀석의 활용법은 무궁무진할 것이다. 예를 들어 b라는 변수에 a라는 배열의 마지막 값을 할당하고 싶지만 a가 빈 배열이면 1을 할당하고 싶을 땐 다음과 같이 심플하게 끝낼 수 있다.

let a = [1, 2, 3, 4];
let b = a[a.length - 1] || 1;

a가 빈 배열이라면 a[a.length - 1]이 undefined가 되고 이는 false로 평가되기 때문에 1이 할당될 것이다. 

 

 

지금까진 ||를 변수 할당 시에 이용해먹는 방법이 대해 알아봤고, 이젠 &&를 변수 할당 시에 이용할 수 있는 방법을 소개하겠다. 나는 ||는 직관적으로 잘 이해된 것에 비해 &&가 살짝 헷갈렸는데, 이 연산자들의 성질을 안다면 이해하기 좀 쉬울 것이다. 이 논리연산자들의 성질은 다음과 같다.

 

1. ||는 첫 번째 피연산자가 true면 뒤에 놈은 신경도 안 쓰고 바로 true를 내뱉는 성격이 급한 애다. 뒤에 놈은 첫 번째 피연산자가 false일 때만 쳐다본다.

2. &&는 첫 번째 피연산자가 false면 뒤에 놈은 신경도 안 쓰고 바로 false를 내뱉는 성격이 급한 애다. 뒤에 놈은 첫 피연산자가 true일 때만 쳐다본다.

 

이걸 학교 과제에서 이용할 때 ||이나 &&의 좌우로 수식을 써놓고 특정 상황에선 그 수식이 수행되고 어떤 상황에선 안 수행되고 이런 식으로 코드를 짰었는데..

 

암튼 각설하고, ||가 첫 피연산자가 참으로 평가되면 첫 피연산자를 리턴하고 그게 아니면 두 번째 피연산자를 리턴했듯이, 

&&는 첫 피연산자가 거짓으로 평가되면 첫 번째 피연산자를 리턴하고 그게 아니면 두 번째 피연산자를 리턴한다. 바로 위에서 소개한 성질이 있으니까! 

 

즉 다음 코드의 결과는 a = null이다.

a = 100 && 200 && null && 300; // a = null

 

참고로..엄밀히 말하자면 ||의 경우 첫 피연산자가 참으로 평가되면 첫 피연산자를, 그게 아니면 두 번째 피연산자를 리턴한다고 했는데 사실 왼쪽에서 오른쪽으로 피연산자를 하나하나 평가하면서 참으로 평가되는 녀석이 있으면 바로 그 녀석을 리턴하고, 모든 피연산자가 거짓으로 평가되는 경우엔 마지막 피연산자를 리턴하는 것이다. 근데 결론적으론 첫 피연산자가 거짓으로 평가되면 두 번째 피연산자를 리턴하는 꼴과 같다는 말에서 이렇게 쓴 것. &&도 이와 마찬가지다

 


이 글을 쓰고 나중에 다른 곳에서 강의를 들으며 이 내용이 나와서 정리.

JS에서 &&는 왼쪽 값이 true로 평가되면 오른쪽 값을 리턴. 반대로 왼쪽 값이 false로 평가되면 그 값을 리턴

JS에서 ||는 왼쪽 값이 true로 평가되면 왼쪽 값을 리턴, 반대로 왼쪽 값이 false로 평가되면 오른쪽 값을 리턴

이 두 줄로 정리된다.

 

+ Recent posts