Frontend/Study

[모던 자바스크립트 Deep Dive] 09 ~ 11장

BeNI 2023. 6. 2. 17:32
728x90

09장  타입 변환과 단축 평가

 

1. 타입 변환

1) 명시적 타입 변환(explicit coercion) / 타입 캐스팅

: 개발자가 의도적으로 값의 타입을 변환 하는 것

var x = 10;
var str = x.toString(); // 숫자를 문자열로 타입 캐스팅

 

2) 암묵적 타입 변환

: 개발자의 의도와는 상관없이 자바스크립트 엔진에 의해 암묵적으로 타입이 자동 변환되는 것

var x = 10;
var str = x + ''; // typeof str = string

 

👉 명시적/암묵적 타입 변환은 기존 원시 값을 직접 변경하는 것이 아니라, 새로운 원시 값을 생성하는 것!

 

2. 암묵적 타입 변환

1) 문자열 타입으로 변환

1 + '2' // "12"
NaN + '' // "NaN"
true + '' // "true"
null + '' // "null"
(Symbol()) + '' // Error
({}) + '' // "[object Object]"
[] + '' // ""
[10, 20] + '' // "10,20"
(function(){}) + '' // "function(){}"
Array + '' // "function Array() { [native colde] }"

➕(더하기)연산자의 피연산자 중 하나 이상이 문자열일 시 자동 형변환

 

2) 숫자 타입으로 변환

1 - '1' // 0
1 * '10' // 10
1 / 'one' // NaN

➕(더하기)연산자를 제외한 산술 연산자는 피연산자를 암묵적으로 숫자 타입으로 변환

만약, 숫자 타입으로 변환할 수 없는 경우는 평가 결과가 NaN이 됨

 

'1' > 0 // true
+'' // 0
+'0' // 0
+'1' // 1
+true // 1
+false // 0
+null // 0
+undefined // NaN
+Symbol() // Error
+{} // NaN
+[] // 0
+[10, 20] //NaN
+(function(){}) // NaN
빈 문자열, 빈 배열, null, false는 0으로 치환, true는 1로 변환됨

 

3) 불리언 타입으로 변환

- 자바스크립트 엔진은 조건식의 평가 결과를 불리언 타입으로 항상 암묵적 타입변환한다.

- 불리언 타입이 아닌 값은 Truthy 또는 Falsy 값으로 구분한다.

📌 Falsy 값 : false, undefined, null, 0, -0, NaN, 빈 문자열

 

 

3. 명시적 타입 변환

1) 문자열 타입으로 변환

  • String 생성자 함수를 new 연산자 없이 호출하는 방법
  • Object.prototype.toString 메서드를 이용하는 방법
  • 문자열 연결 연산자를 이용하는 방법
String(true); // "true"
(true).toString() // "true"
true + ''; // "true"

2) 숫자 타입으로 변환

  • Number 생성자 함수를 new 연산자 없이 호출하는 방법
  • parseInt, parseFloat 함수를 이용하는 방법(문자열만 가능)
  • + 단항 산술 연산자를 이용하는 방법
  • * 산술 연산자를 이용하는 방법
Number('false'); // 0
parseInt('0'); // 0
parseInt(false); // NaN
+'0' // 0
'0' * 1; // 0

 

3) 불리언 타입으로 변환

  • Boolean 생성자 함수를 new 연산자 없이 호출하는 방법 
  • !! (부정 연산자 두번) 을 이용하는 방법
Boolean(''); // false
!!''; // false

!!NaN; // false
!!Infinity; // true
!!null; // false
!!undefiend; // false
!!{}; // true
!![]; // true

📌 Infinity, 빈 객체, 빈 배열은 true 값이다 !

 

4. 단축 평가

1) 논리 연산자를 사용한 단축 평가

:  표현식을 평가하는 도중 평가 결과가 확정된 경우 나머지 평가 과정을 생략하는 것

📌 &&, || 연산자는 논리 연산의 결과를 결정하는 피연산자를 타입변환하지 않고 그대로 반환

 

단축 평가 표현식 평가 결과
true || anything true
false || anything anything
true && anything anything
false && anything false

 

    👉 사용하는 경우
  • 객체라고 예상하는 변수가 null / undefined가 아닌지 확인하고 프로퍼티를 참조할 때
  • 함수 매개변수에 기본 값을 설정할 때 

 

 

2) 옵셔널 체이닝 연산자

- es11에서 도입된 옵셔널 체이닝 연산자는 좌항의 피연산자가 null / undefined 인 경우 undefiend를 반환하고, 

  그렇지 않으면 우항의 프로퍼티를 참조

var elem = null; 

var value1 = elem?.value; // undefined
var value2 = elem && elem.value; //null

- 논리 연산자 &&가 좌항 피연산자가 Falsy 값이 면 좌항 피연산자를 그대로 반환하는 경우에 반면,

  옵셔널 체이닝 연산자는 null 또는 undefined가 아니면 우항의 프로퍼티 참조를 이어간다

var str = '';

var length = str && str.length; // ''
var length = str?.length; // 0

 

3) null 병합 연산자

- es11에서 도입된 null 병합연산자 ?? 는 좌항의 피연산자가 null 또는 undefiend인 경우 우항의 피연산자를 반환하고, 

  그렇지 않으면 좌항의 피연산자를 반환함 (변수의 기본값을 설정할 때 유용)

var foo = null ?? 'default string'; // 'default string'

var foo = '' || 'default string'; // 'default string'
var foo = '' ?? 'default string'; // ''

|| 연산자와의 차이점은, 좌항의 피연산자 값이 Fasly 값이라도 null / undefined가 아니면 좌항의 피연산자 값을 반환

(기본값이 0, 빈 문자열으로도 유효하다면 필요하다)

 

 

 

10장  객체 리터럴

1. 객체란?

  • 자바스크립트는 객체 기반 프로그래밍 언어, 원시 값을 제외한 나머지는 "객체"로 구성되어 있음 
  • 객체는 원시 값과 다르게 변경 가능한 값이다. 
  • 객체는 0개 이상의 프로퍼티로 구성된 집합, 키와 값으로 구성된다.

✅ 프로퍼티와 메서드

  • 프로퍼티 : 객체의 상태를 나타내는 값
  • 메서드: 프로퍼티를 참조하고 동작할 수 있는 동작 (프로퍼티 값이 함수 일 때)

 

 

2. 객체 리터럴에 의한 객체 생성

1) 생성 방법들

  • 객체 리터럴
  • Object 생성자 함수
  • 생성자 함수
  • Object.create 메서드
  • 클래스(es6)

2) 리터럴을 이용한 생성 방법

- 중괄호 내에 0 개 이상의 프로퍼티를 정의

var person = {
  name: 'Kim',
  sayHello: function () {
    console.log(`hello! ${this.name}`);
  }
}

 

3. 프로퍼티 

- 객체는 프로퍼티의 집합이며 프로퍼티는 키과 값으로 구성된다.

  • 프로퍼티 키 : 빈 문자열을 포함하는 모든 문자열 또는 심벌 값
    • 예약어를 프로퍼티 키로 사용 가능하다 (권장 x)
    • 프로퍼티 키를 중복 선언 하면 나중에 선언한 프로퍼티 키 값이 앞서 선언 한 값을 덮어쓴다.
  • 프로퍼티 값: 자바스크립트에서 사용할 수 있는 모든 값

* 프로퍼티 키값이 식별자 네이밍 규칙을 따를 때는 따옴표를 생략할 수 있다.

var person = {
  firstName : 'kim', // 네이밍 규칙 준수
  'last-name' : 'euna' // 네이밍 규칙 준수 x
}

 

✅ 동적 키 값 생성 하기

- 프로퍼티 키를 사용할 표현식을 대괄호로 묶어야 한다.

var obj = {};
var key= 'hello';

obj[key] = 'world';

 

4. 프로퍼티 접근

1) 접근 방법

  • 마침표 프로퍼티 접근 연산자를 사용하는 마침표 표기법
  • 대괄호 프로퍼티 접근 연산자를 사용하는 대괄호 표기법
var person = {
  name: 'Kim'
};

console.log(person.name);
console.log(person['name']); // 반드시 따옴표로 감싸야 함 아니면 식별자로 인식

📌 객체에 존재하지 않는 프로퍼티에 접근하면 undefined를 반환 !!!!

 

프로퍼티 키가 식별자 네이밍 규칙을 준수하지 않는 이름일 때, 대괄호 표기법을 이용 !

단, 숫자로 이루어진 키면 따옴표를 생략할 수있다.

오ㅋ

➕ 주의 할 점

perosn.last-name; // 브라우저 환경 : NaN
                  // Node.js 환경: Error

person.last값이 없으므로 undefiend로 평가, undefined-name 이면 name이라는 식별자를 찾는데,

브라우저 환경에서는 name이 window를 가르킨다(기본 값 빈 문자열) 따라서 undefiend-'' => NaN 값이다.

 

 

 

5. 프로퍼티 삭제

- delete 연산자를 이용한다

var person = {
  name: 'Lee'
};

person.age = 20; // 프로퍼티 동적 생성
delete person.age; // 프로퍼티 삭제

* 존재하지 않는 프로퍼티를 삭제해도 에러는 안난다.

 

 

6. 객체 리터럴 확장 기능

1) 프로퍼티 값으로 변수를 사용하는 경우, 변수 이름과 프로퍼티 키가 동일한 이름일 때 프로퍼티 키 생략 가능

let x = 1, y = 2;

const obj = { x, y };

2) 계산된 프로퍼티 이름

- 값으로 변환 되는 표현식을 사용해 프로퍼티 키를 동적으로 생성할 수 있다.

var x = 'abc';
var i = 0;

var obj = {};

obj[x + '-' + ++i] = i; // { abc-1: 1 }
obj[`${x}-${++i}`] = i;

const obj2 = {
  [`${x}-${++i}`]: i
}

3) 메서드 축약 표현

var obj = {
  sayHi: function() {},
  sayHello() {} // es6
};

es6의 메서드 축약 표현으로 정의한 메서드는 프로퍼테 할당한 함수와 다르게 동작한다.

 

 

 

11장  원시 값과 객체의 비교

 

1. 원시 값

- 변경 불가능한 값 

- 원시 값을 변수에 할당하면 변수에는 실제 값이 저장된다.

- 불변성을 갖는 원시 값을 할당한 변수는 재할당 이외에 변수 값을 변경할 수 있는 방법은 없다.

(재할당시 새로운 메모리 공간을 확보하고 변수가 참조하던 메모리 공간의 주소를 변경한다)

 

1) 문자열과 불변성

- 원시 타입 별로 메모리 공간의 크기가 미리 정해져 있다

  • 문자열 타입 : 2byte(1개의 문자)
  • 숫자 타입 : 8byte

- 자바스크립트는 개발자의 편의를 위해 문자열 타입을 제공한다. 

- 문자열 또한 원시 값이며, 생성 이후엔 변경 불가능하다.

var str = 'string';
str[0] = 'S'; // 배열처럼 접근 가능하다

console.log(str); // string (변경되지 않음)

 

 

2. 값에 의한 전달

var score = 80;
var copy = score;

score = 100;
console.log(score); // 100
console.log(copy); // 80

변수에 변수를 할당했을 때는, 변수의 값이 새로운 변수 값으로 생성되어 할당된다.

(copy에 score를 할당했을 때, 80이라는 값이 새롭게 생성되어 copy 변수에 할당된다)

👉 값에 의한 전달

 

따라서 score 변수와 copy 변수에 들어간 80 은 다른 메모리 공간에 저장된 별개의 값이다.

 

 

- 사실 자바스크립트에서 "값에 의한 전달" 이라는 용어는 없다.

변수에는 값이 전달되는게 아니라 메모리 주소가 전달되기 때문에 식별자는 값이 아니라 메모리 주소를 기억한다.

var x = 10; // 할당 연산자에 의해 x라는 식별자는 10이 저장된 메모리 주소가 할당된다.

 

아래 예제는 두가지로 해석이 가능하다.

var copy = score;
  • 새로운 80을 생성(복사)해서 메모리 주소를 전달하는 방식(두 변수의 메모리 주소가 다르다)
  • score 변수값 80의 메모리 주소를 그대로 전달하는 방식(두 변수의 메모리 주소가 같다)

 

3. 객체

- 자바스크립트 객체는 프로퍼티 키를 인덱스로 사용하는 해시테이블과 비슷한 형태로 구현되어있다.

- 자바/C++ 처럼 클래스 기반으로 객체를 생성하는 반면, 자바스크립트는 클래스 없이 객체 생성이 가능하다.

  따라서 동적으로 프로퍼티나 메서드를 추가할 수 있다는 장점이 있지만 성능면에서는 비효율적이다.

* V8 자바스크립트 엔진에서는 프로퍼티에 접근하기 위해 동적 탐색 대신 히든 클래스를 사용해 성능을 개선했다.

 

1) 변경 가능한 값

- 객체 타입의 값은 변경 가능한 값 !

- 객체를 변수에 할당하면, 변수는 실제 객체가 저장되어 있는 메모리 주소를 참조 값을 가르킨다.

 

➕ 원시값을 변수에 할당하면 "변수는 O값을 갖는다/O 값이다" 라고 표현하는 대신, 

      객체를 할당한 변수는 변수는 "객체를 참조하고 있다/가르키고 있다" 라고 표현한다

 

👉 객체를 할당한 변수는 재할당 없이 객체를 직접 변경할 수 있다 !

 

- 이런 객체의 구조적 설계는 여러개의 식별자가 하나의 객체를 공유할 수 있다는 부작용이 있다.

 

2) 얕은 복사 vs 깊은 복사 ⭐⭐⭐⭐⭐⭐

  • 얕은 복사 : 참조 값을 복사 (객체 안에 객체가 있을 경우 한 개의 객체라도 기존 변수의 객체를 참조하고 있다면 이를 얕은 복사라고 합니다)
  • 깊은 복사 : 객체의 실제 값 복사 (객체에 중첩되어 있는 객체까지 복사)
const obj = { x: { y: 1 } };

// 얕은 복사
const c1= { ...obj };
console.log(c1 === o); // false
console.log(c1.x === o.x); // true

위 예제에서는 obj의 x 객체와 c1의 x 객체가 같은 참조값을 갖고 있기에 얕은 복사라고 한다.

이 외에 Array.prototype.slice() 메서드, Object.assgin() 메서드도 얕은 복사다.

 

* 깊은 복사 방법 

  • lodash의 cloneDeep() 메서드 사용
  • JSON.parse, JSON.stringfy 이용
  • 재귀 함수를 이용한 복사 방법

3) 참조에 의한 전달

var person = {}

var copy = person;

위 예제에서는 person과 copy가 하나의 객체를 공유한다 (같은 메모리 주소값을 참조한다)

따라서 하나라도 변경하면 다른 것도 같이 변경된다.

 

 

👉 "값에 의한 전달" 과 "참조에 의한 전달"  ?

자바스크립트에서는 "참조에 의한 전달" 은 존재 하지 않는다.

모두 값에 의한 전달 방식이고, 차이는 변수에 저장되어 있는 값이 원시 값인지, 참조 값인지에 따라 달라진다

* 공유에 의한 전달이라고 표현하기도 한다.

 

 

 

 

728x90