heyday2024 님의 블로그
[모던 자바스크립트_스터디] 6~9장 새롭게 알게된 개념과 중요 개념 정리 본문
6장: 데이터 타입
저번 시간에 끝까지 읽지 못해서 간략하게 정리.
- 원시타입: number, string, boolean, undefined, null, symbol
- 객체 타입: object, function, array
<Escape sequence: 일반적인 문자로 표현할 수 없는 특별한 문자를 나타내기 위해 사용되는 일련의 문자 >
\' | 작은따옴표 (') |
\" | 큰따옴표 (") |
\\ | 백슬래시 () |
\n | 줄 바꿈 (Newline) |
\r | 캐리지 리턴 (Carriage Return): 커서를 처음으로 이동. |
\t | 수평 탭 (Tab) |
\b | 백스페이스 (Backspace) |
\f | 폼 피드 (Form Feed) |
\v | 수직 탭 (Vertical Tab) |
\0 | 널 문자 (Null Character) |
\uXXXX | 유니코드 문자, XXXX는 4자리 16진수, 예시로 '\u0041'은 'A' |
\xXX | 16진수 ASCII 문자, XX는 2자리 16진수 |
<템플릿 리터럴 (template literal)>
새로운 문자열 표기법: 백틱(graves: ``) 사용
편리한 문자열 처리 기능 제공
- multi-line string: 줄바꿈 허용
- expression interpolation: 연산자 +로 문자열 연결
- tagged template: ${변수, 연산 등 가능}
<Symbol>
변경 불가능한 원시 타입의 값
다른 값과 중복되지 않는 유일 무이한 값
--> 주로 이름이 충돌할 위험이 없는 객체의 유일한 프로퍼티 키를 만들기 위해 사용함!!!
const uniqueSymbol = Symbol("description");
console.log(typeof uniqueSymbol); // "symbol"
심볼 생성
const symbol1 = Symbol("test");
const symbol2 = Symbol("test");
console.log(symbol1 === symbol2); // false (각각의 Symbol은 고유함)
놀랍게도 Symbol은 각 인스턴스가 항상 고유하므로 동일한 설명(내용)을 가진 Symbol도 서로 다른 값으로 간주
const myObject = {
[Symbol("uniqueKey")]: "value1",
normalKey: "value2"
};
console.log(myObject[Symbol("uniqueKey")]); // undefined
// `Symbol`을 사용해 만든 키는 위와 같이 찾을 수 없음.
const uniqueKey = Object.getOwnPropertySymbols(myObject)[0]; // 유일한 Symbol 키 가져오기
console.log(myObject[uniqueKey]); // "value1"
이런 식으로 객체의 속성으로 사용함(키의 보안이 정말 중요할 때 쓰지만, Symbol이라는 데이터 타입이 보통 잘 쓰이진 않음.)
<*******************매우 중요******************>
자바스크립의 변수는 선언이 아닌 할당에 의해 타입이 결정(타입 추론 type inference)!!!!!
그리고 재할당에 의해 변수의 타입은 언제든지 동적으로 변할 수 있음 === 동적 타이핑(dynamic typing)
그래서 자바스크립트 언어는 동적 타입 언어(dynamic/weak type language)이다.
하지만 이런 장점있는만큼 단점도 존재하는법, trade-off로
1. 변수 값이 언제든 변경될 수 잇기 때문에 복잡한 프로그램에서는 변화하는 변수 값을 추적하기 어려움
2. 개발자의 의도와 상관없이 JS 엔진에 의해 암묵적으로 데이터 타입이 자동으로 변환될 수도 있음
3. 안정적인 프로그램을 만들기 위해 변수 사용 전, 데이터 타입을 체크해야하는 경우가 있는데 이는 매우 번거롭고 코드의 양도 증가시키는 비효율를 초래함.
---> 즉, 동적 타입 언어는 유연성은 높지만, 신뢰성이 떨어지는 편....
TIP.
- 변수는 꼭 필요한 경우에 한해 제한적으로 사용. (변수 무분별한 생성, 남발 자제)
- 변수의 유효범위(스코프)는 최대한 좁게 만들어 변수의 부작용 억제.(오류 확률 줄이기)
- 전역변수 사용 자제
- 변수보다는 상수 사용으로 값의 변경을 방지(let 보다는 const를 주로 사용하자!!!)
- 변수 이름은 변수의 목적, 의미를 파악할 수 있도록 네이밍하자!!!(이건 튜터님들고 강조하신 내용!!!!)
- 무작정 짧은거?? 신박한거??? NO!!! 가독성이 좋은 코드가 좋은 코드이다!!!!
7장: 연산자
operator 로 operand를 operation해서 새로운 값을 만듭니다~~~~😉
operation 종류: 산술, 할당, 비교, 논리, 타입, 지수 연산
<증감 연산자>
증감 연산자 (++, --) 는 피연산자의 값을 변경하는 부수 효과가 있음.
- 전위 증감 연산자(prefix increment/decrement operator): ++x, 피연산자 값 증감 후 --> 다른 연산 수행
- 후위 증감 연산자(postfix increment/ decrement operator): x--, 다른 연산 수행 후 --> 피연산자 값 증가
let x = 5;
//선할당 후증가(postfix increment operator)
let result = x++;
console.log(result, x); //5, 6
//선증가 후할당(prefix increment operator)
result = ++x;
console.log(result, x); //7, 7
//선할당 후감소(postfix decrement operator)
result = x--;
console.log(result, x); //7, 6
//선감소 후할당(postfix decrement operator)
result = --x;
console.log(result, x); //5, 5
<이항 binary 산술 연산자> +, -, *, /, % ===> 피연산자가 두개임
<단항 unary 산술 연산자> +, -, ++, -- ===> 피연산자 1개임.
+ 연산자는 피연산자 중 하나 이상이 문자열이면 문자열을 연결하는 연산자가됨
----> 암묵적 타입 변환(implicit coercion)/ 타입 강제 변환 (type coercion)
<할당 연산자 assignment operator>
= , +=, -=, *=, /=, %=
<비교연산자 Comparison Operator>
- 동등비교 loose equality : ==
- 일치비교 strict equality : ===
<삼항 조건 연산자 ternary operator>
조건식 ? true일 때 값: false일때 값
<논리 연산자 logical operator>
&&, ||, !
<쉼표 연산자>
var x, y, z;
x=1, y=2, z=3; //3
왼쪽부터 차례대로 피연산자 평가하고 마지막 평가가 끝나면 마지막 피연산자의 평가 결과 반환
<그룹 연산자>
()
<typeof 연산자>
string, number, boolean, undefined, symbol, object, function 중 하나 반환
- null을 반환하는 경우는 없음(null은 object로 반환함: 공식적인 오류)
- 선언 안 한 식별자는 Reference Error가 아닌 undefined로 반환함.
<지수exponent 연산자>
**
Math.pow()
<연산자 우선 순위>
우선순위 | 연산자 |
1 | () |
2 | new(매개변수 존재), . , [](프로퍼티 접근), ()(함수호출), ? .(옵셔널 체이닝 연산자) |
3 | new(매개변수 존재) |
4 | x++, x-- |
5 | !x, +x, -x, ++x, --x, typeof, delete |
6 | ** |
7 | *, / % |
8 | +, - |
9 | < , <=, > , >=, in , instanceof |
10 | ==, !=, ===, !== |
11 | ??(null 병합 연산자) |
12 | && |
13 | || |
14 | ? ... : ... |
15 | 할당 연산자 |
16 | , |
<그 외 연산자>
연산자 | 개요 |
?. | 옵셔널 체이닝 연산자 |
?? | null 병합 연산자 |
delete | 프로퍼티 삭제 |
new | 생성자 함수 호출 시 인스턴스 생성 |
instanceof | 좌변의 객체가 우변의 생성자 함수와 연결된 인스턴스인지 판별 |
in | 프로퍼티 존재 확인 |
- 할당 연산자, 증감 연산자, delete 연산자는 부수효과가 있음
8장: 제어문 (control flow statement)
조건에 따라 코드 블록을 실행(조건문)하거나 반복실행(반복문)
<블록문 block statement/ compound statement>
0개 이상의 문을 중괄호로 묶은 것, 코드 블록!
- if- else
- 삼항 조건 연산자 표현식으로 바꿀 수 있으나, 이 표현식은 값처럼 사용할 수 있기 때문에 변수에 할당할 수 있음. 하지만 if-else 문은 표현식이 아닌 문!!(값 할당 안됨)
- switch
- 꼭 case 마다 break; 넣어주기(항상 까먹냐고 왜....)
- 그리고 다 해당 안된다~하면 선택사항이긴한데 default 사용
- for
- while
- do - while
- break(코드 블록 탈출), continue(현 지점 중단 루 실행 흐름 이동)
-
-
-
for (var i = 0; i < string.length; i++){
if(string[i] !== search) continue;
count++; ?/continue 문이 실행되면 여기 코드는 실행안됨.
}
9장: 타입 변환과 단축 평가
명시적 타입 변환(explicit coercion)/ 타입 캐스팅 (type casting)
: 개발자가 의도적으로 특정 값을 원하는 타입으로 변환하는 것
- 보통 함수나 연산자를 사용하여 타입을 명확하게 변환
// 숫자를 문자열로 변환
let num = 123;
let str = String(num); // 명시적 변환
console.log(typeof str); // "string"
// 문자열을 숫자로 변환
let strNum = "456";
let num2 = Number(strNum); // 명시적 변환
console.log(typeof num2); // "number"
// Boolean으로 변환
let boolVal = Boolean(0); // 명시적 변환 (0은 false)
console.log(boolVal); // false
기존 원시 값 자체를 변경하는 것이 아님 앞서 원시형, 참조형 복사 때 배웠듯이, 원시 값은 immutable value로 변경이 불가능해서 다른 원시값을 생성하고 그것을 참조하는 것과 다름없음.
- 표준 빌트인(built-in) 생성자 함수
- String()
- .toString()
- Number()
- parseInt
- parseFloat()
- + (문자열 -> 숫자 ex: +'0' // 0)
- + (boolean -> 숫자 ex: +true //1)
- * (문자열 --> 숫자 ex: '0' * 1; //0)
- * ( boolean -> 숫자 ex: true * 1 //1)
- Boolean()
- !! (부정 논리 연산자 두번)
암묵적 타입 변환(implicit coercion)/ 타입 강제 변환 (type coercion)
: JavaScript 엔진이 자동으로 발생시키는 변환으로, 개발자가 명시적으로 변환하지 않았음에도 불구하고, 상황에 따라 타입이 강제로 변환
- 연산자와 함께 사용될 때 자주 발생
// 숫자와 문자열의 덧셈
let result1 = 5 + "5"; // 숫자 5가 문자열로 변환되어 "55"가 됨
console.log(result1); // "55"
// 숫자와 문자열의 뺄셈
let result2 = "10" - 5; // 문자열 "10"이 숫자로 변환되어 계산
console.log(result2); // 5
// Boolean과 숫자의 연산
let result3 = true + 2; // true가 숫자 1로 변환되어 1 + 2 = 3
console.log(result3); // 3
// null과 숫자의 연산
let result4 = null * 2; // null은 0으로 변환되어 0 * 2 = 0
console.log(result4); // 0
// 비교 연산자
let result5 = "5" == 5; // 문자열 "5"가 숫자 5로 변환되어 비교됨
console.log(result5); // true
console.log(!0) //true
console.log(1/'one') //NaN
console.log( +null) //0
암묵적 타입 변환은 에측 가능한 수준, 범위여야함. 그렇지 못하면, 오류를 초래할 수 있음.
<단축 평가 short-circuit Evaluation>
논리 연산의 결과를 결정하는 피연산자를 타입 변환하지 않고 그대로 반환함
단축평가는 표현식을 평가하는 도중에 평가 결과가 확정된 경우 나머지 평가 과정을 생략하는 것
단축평가 | 평가 결과 |
true || anything | true |
false || anything | anything |
true && anything | anything |
false && anything | false |
언제 유용하게 사용함??
- 객체를 가리키기를 기대하는 변수가 null 또는 undefined가 아닌지 확인하고 프로퍼티 참조할 때
- 객체가 null 또는 undefined일 때 오류 없이 안전하게 프로퍼티를 참조
- 옵셔널 체이닝(?.)이 등장하기 전에는 주로 단축 평가가 많이 사용되었음. 하지만 요즘은 옵셔널 체이닝이 더 가독성 좋고 권장됨.
let user = null;
// user가 null 또는 undefined가 아닐 때만 user.name을 참조
console.log(user && user.name); // null (undefined를 반환하지 않고, 오류도 없음)
user = { name: 'John' };
console.log(user && user.name); // 'John' (정상적으로 참조)
2. 함수 매개변수에 기본값 설정할 때
- 단축 평가는 함수 매개변수가 undefined일 때 기본값을 설정하는 간단한 방법으로 사용할 수 있음
function greet(name) {
name = name || 'Guest'; // name이 falsy 값일 때 'Guest'로 설정
console.log(`Hello, ${name}!`);
}
greet(); // Hello, Guest!
greet('Alice'); // Hello, Alice!
greet의 매개변수가 전달되지 못했을떄 기본값 출력
<옵셔널 체이닝 optional chaining 연산자 >
?.
좌항의 피연산자가 null 또는 undefined인 경우 undefined 반환, 그렇지 않으면 우항의 property 참조 이어감.
- 좌항의 객체가 null 또는 undefined인 경우, 에러를 발생시키지 않고 undefined를 반환.
- 객체가 존재할 때만 우항의 프로퍼티나 메서드를 호출
- 중첩된 객체 구조에서도 안전하게 접근 가능
let user = null;
console.log(user?.name); // undefined (user가 null이므로 에러 없이 undefined 반환)
user = { name: 'Alice' };
console.log(user?.name); // 'Alice' (정상적으로 name 참조)
<null 병합 연산자 nullish coalescing>
??
좌항의 값이 null 또는 undefined인 경우에만 우항의 값을 반환
let name;
let defaultName = "Guest";
let userName = name ?? defaultName;
console.log(userName); // 'Guest' (name이 undefined이므로 defaultName 반환)
name = "Alice";
userName = name ?? defaultName;
console.log(userName); // 'Alice' (name이 null이나 undefined가 아니므로 name 반환)
- falsy 값과 차이
let count = 0;
let result = count ?? 10;
console.log(result); // 0 (count가 null이나 undefined가 아니므로 0 반환)
result = count || 10;
console.log(result); // 10 (0은 falsy 값이므로 10 반환)
|| 연산자는 0, false, "" 같은 falsy 값도 기본값으로 처리해버리지만, ?? 연산자는 오직 null과 undefined만 기본값 처리
'스터디' 카테고리의 다른 글
[modern JS deep dive] 13장 ~15장: 스코프, 전역변수의 문제점, let const와 블록 레벨 스코프 (0) | 2024.10.25 |
---|---|
[모던 자바스크립트 스터디]10~12장(객체 리터럴, 원시 값과 객체의 비교, 함수) 정리 (1) | 2024.10.22 |