[01.09] Js 공부(2)

오늘처음해요·2024년 1월 9일
0

오늘도 자바스크립트 강의를 듣는데

내가 아는 내용과 살짝 다른 설명을 들었다.

class의 super 관련 설명이었는데

class Food {
  constructor(name) {
    this.name = name;
  }
}
  
class Ramen extends Food {
  constructor(name, side) {
    super(name);
  }
  eat() {
    return this.name + '맛있다';
  }
}
  
const ramen = new Ramen('Nuguri');
  
console.log(ramen.eat()); // Nuguri 맛있다

이런 코드에서 super(name)가 있기에
부모 생성자 호출하여 this에 name을 저장할 수 있었고
그래서 eat() 을 호출하면 Nuguri 맛있다가 나온다고 설명을 하셨는데

class Food {
  constructor(name) {
    this.name = name;
  }
}
  
class Ramen extends Food {
  eat() {
    return this.name + '맛있다';
  }
}
  
const ramen = new Ramen('Nuguri');
  
console.log(ramen.eat()); // Nuguri 맛있다

사실 Ramen은 애초에 Food를 상속받았기 때문에 super()를 호출하지 않아도

const ramen = new Ramen('Nuguri');

생성을 하면 자동으로 ramen.name = 'Nuguri'가 된다.

따라서 예시는 클래스의 super()를 쓰긴 했지만 활용했다고 보긴 어렵다
(안써도 결과값은 똑같기 때문에)

super()의 활용을 제대로 보여주는 예시가 되려면

class Food {
  constructor(name) {
    this.name = name;
  }
}
  
class Ramen extends Food {
  constructor(name, side) {
    super(name);
    this.side = side;
  }
  eat() {
    return this.name + '맛있다';
  }
}
  
const ramen = new Ramen('Nuguri', 'Fried egg');
  
console.log(ramen.eat()); // Nuguri 맛있다
console.log(ramen.side); // Fried egg

이런 식으로 자식 클래스에 새로운 속성 값을 저장할 때를
예시로 드는 게 적절하지 않을까 생각했다.

"부모 클래스의 constructor에서 인자를 받고 있는 경우
(자식 클래스 constructor에서) super에 인자를 넘겨서 호출 해야합니다"

라고 설명하셔서

'내가 잘못알고 있나...?' 생각이 들어

자식 클래스에서 필수적으로 super를 호출해야 하는지 혹은
관련한 코드 컨벤션이 있나 찾아봤지만

강사님의 설명과 비슷한 건 아직 발견하지는 못했다...


Javascript

Class

extends

부모 클래스를 상속받는 자식 클래스를 정의할 때 사용

class ramen extends Food {
  constructor(name) {
    super(name); // Food의 constructor를 실행
  }
}

super()는 자식 클래스의 constructor 사용 시 constructor 반환문 전에 사용 되어야 함.

Static

정적 메서드

클래스의 인스턴스를 생성하지 않아도 호출할 수 있는 메서드를 만들 때 사용


Object

Collection

Map

키와 값을 서포 매핑시켜 저장함

저장된 순서대로 요소를 반복적으로 접근할 수 있음

[key, value] 의 형태로 삽입된 순서대로 추가

요소 접근, 포함 여부 - get, has
요소 변경 - clear, delete, set
순환 관련 - keys, values, entries, forEach

Map과 객체와의 다른점

  • object는 string, Symbol 데이터 타입만 키 값으로 지정이 가능한데
    Map은 모든 값을 키로 활용 가능
  • Object prototype의 기본 속성과 동일한 키를 생성 시 에러 발생
    Map은 기본적으로 갖고있는 속성이 없음
  • 객체의 크기를 확인할 때 Object는 따로 처리해야 함. Map은 내장된 size 활용하면 됨
  • object는 순서가 보장이 안됨. Map은 순서 보장됨
  • Object는 iterable이 아님, Map은 iterable
  • 빈번한 키,값의 추가 제거에는 Map을 쓰면 좋음
  • 직렬화와 구문 분석 제공(JSON.stringify, JSON.parse) / Map은 제공 안됨

WeakMap

키에 대한 강력한 참조를 생성하지 않는 키/값 쌍의 모음

키는 object만 사용 가능

객체 정보를 비노출 => 객체의 사적인 정보를 저장하기 위해서, 상세 구현 내용을 숨기기 위해서 사용함

Set

모든 값들의 집합
특정 값은 set 내에 하나만 존재
for ... of를 통해 순회 가능

요소 제거나 포함 여부를 확인할 때 배열보다 좋음

set은 has로 간단히 포함 여부 확인 가능
delete로 간단히 삭제 가능

요소 접근, 포함 여부 - has
요소 변경 - clear, delete, add


객체 메서드

객체 복사 assign
객체 신규 생성 create
객체 고정 freeze, preventExtensions, seal
객체 상태 확인 isExtensible, isFrozen, isSealed

객체를 배열로 반환 entries, fromEntries
객체 프로토타입 getOwnPropertyOf, setOwnProperty

깊은 복사

deep copy

  1. 재귀함수를 이용한 복사 (라이브러리 : lodash-cloneDeep)
  2. JSON.stringify (객체 -> 문자열로 변환(참조가 끊어짐) -> 객체로 변환)
const obj = { name: 'chan' }
const objStr = JSON.stringify(obj) // 문자열화 { 'name' : 'chan' }
const newObj = JSON.parse(objStr) // 객체화 { name : 'chan' }

얕은 복사

복사된 객체의 속성 중 하나라도 같은 참조를 하고 있게되면,
얕은 복사로 복사되었다고 한다.

방법
Object.assign({}, 복사할 객체)
spread 연산자 - { ...객체 }

날짜 메서드

연/월/일 : getFullYear(), getMonth(), getDate() === toString(), getDay()
시/분/초 : getHours(), getMinutes(), getSeconds(), getMilliseconds()

UTC로 인해 한국은 9시간 차이나므로, getHours와 getUTCHours만 차이나고 나머지는 동일한 값 반환

UTC로부터 걸린 시간 가져오기(ms) : getTime() === valueOf();
UTC와 현지 시간대 차이 가져오기(분 기준) : getTimezoneOffset();

getMonth - 1월이 0부터 시작
getDay - 일요일이 0부터 시작
toLocalDateString - 현지에 맞는 요일 문자열을 얻을 수 있음

속성 메서드

객체 속성 추가
defineProperty
defineProperties

객체 속성 서술자
getOwnPropertyDescriptor
getOwnPropertyDescriptors

객체 속성 열거
getOwnPropertyNames - 객체 자신의 모든 속성 이름을 배열로 반환
keys - 객체 자신의 열거 가능한 속성 이름을 배열로 반환
getOwnPropertySymbols

속성 값
객체 값 비교 is
객체 값 열거 values

Date객체

1970년 1월 1일 UTC 자정과의 시간 차이를 밀리초 단위로 나타낸 것

그리니치 평균시에 기반해서 GMT라고도 불림

Date().getTimezoneOffset() // 현지 시간대를 분 단위로 반환, 한국은 +9h 이므로 540

ISO8601

YYYY-MM-SSThh:mm:ssZ

혼합된 일시를 표현할 때는 T라는 구분자를 사용(상호협의간 T는 생략 가능)
UTC날짜라는 의미로 Z로 표현한다

Intl 객체

언어에 맞는 날짜, 시간 서식을 적용하기 위한 객체

생성자 함수 : Intl.DateTimeFormat

포멧 결과 : format, formatRange
포맷 결과를 각 단위별로 분해하여 배열화 : formatToParts, formatRangeToParts


Prototype

객체 지향 프로그래밍

객체 : 현실의 개념을 추상화하여 정의

상태를 갖고있고 -> this
행동 -> 메서드
식별자 -> 속성

프로토타입 객체

객체의 인스턴스를 만드는 부모 객체 개념

자바스크립트의 모든 객체는 부모 객체인 프로토타입 객체와 연결

부모 객체의 속성과 메서드를 상속받아 사용 가능

모든 객체는 [[prototype]] 이라는 속성이 있는데 상속을 위해 쓰여짐

__proto__ 접근자 속성으로 접근 가능

프로토타입 체인

객체의 속성 참조 시, 속성이 없는 경우 프로토타입 체인이 동작함

[[Prototype]] 을 통해서 부모 객체를 탐색

모든 객체의 부모는 Object.prototype

End of prototype chain

마지막까지 못찾으면 undefined 반환


etc.

실행 컨텍스트

생성 단계 - Creation Phase

함수와 변수를 기록
외부 환경 참조

실행 단계 - 위에서 아래로 코드가 실행

변수는 값이 할당
함수 실행 코드가 있을 경우, 함수 실행
=> 새로운 함수 실행 컨텍스트 생성 및 함수 실행

실행 컨텍스트의 3가지 종류

  1. global 컨텍스트(전역 컨텍스트) -함수 내에서 실행되는 코드가 아니라면, 전역컨텍스트에서 실행
  2. functional 컨텍스트 - 함수가 호출될 때마다, 함수에 대한 실행 컨텍스트 생성, 각 함수들은 자신만의 실행 컨텍스트 존재
  3. eval 컨텍스트

실행 순서

글로벌 컨텍스트 -> 콜 스택에 GEC 추가됨 -> lexical 환경 생성 -> 변수나 함수를 기록 -> 외부 환경을 참조하지만 글로벌은 외부 환경 없음 -> 함수 내의 코드를 제외한 나머지 코드 실행 -> functional 컨텍스트 -> 콜 스택에 FEC 추가됨 -> lexical 환경 생성 -> 함수 내의 코드를 기록 -> 함수는 빌트인 객체를 따르기 때문에 매개 변수의 길이를 나타내는 arguments : { length : 0} ; this : window; baz : undefined 등 기록 됨 -> 외부 환경 참조에서는 GEC를 참조함. -> 함수를 실행 -> 콜스택에서 functional 컨텍스트 빠짐 -> 콜스택에서 글로벌 컨텍스트 빠짐

Call Stack

함수 호출 시 만들어지는 실행 컨텍스트가 쌓임 // 하나의 일만 처리 가능

엔진은 코드를 평가하여 실행 컨텍스트를 만들고 =>
콜 스택에 하나씩 쌓고 콜 스택에서 실행 컨텍스트를 실행하며 =>
스택에서 하나씩 없앤다

this 바인딩

컨텍스트 참조 가능한 키워드 => 객체를 참조하는 역할, 어떤 객체인지 동적으로 결정됨

전역객체에서 this 사용 시
Browser-side : window
Server-side : global

함수 내부의 this는 전역객체에 바인딩
함수 내의 함수도 전역객체에 바인딩

함수 호출 방식 - 객체의 메서드내에 내부 함수가 있을 경우, 함수 호출 방식으로 취급되어 전역 객체를 바라봄

this를 다른 변수에 저장하고 사용하거나

const obj = {
	const that = this; // 이후 this 대신 that 사용
	getWeek() {
		function getDay() {
			console.log(that.day)
		}
	getDay.bind(obj);
	}
}

내부 함수를 해당 객체에 bind 하면 됨

const obj = {
	getWeek() {
		function getDay() {
			console.log(this.day)
		}
	getDay.bind(obj);
	}
}

apply, call

apply(바인딩할 객체, [함수 호출 시 넘기는 인자들])
call(바인딩할 객체, 함수 호출 시 넘기는 인자1, ...)
1. 함수 내의 this에 바인딩할 객체가 바인딩 됨
2. 함수에 인자들이 전달됨
3. 함수 호출됨

바인딩과 동시에 함수를 호출한다.
bind는 함수 호출이 분리되어 있음

클로저

반환된 내부함수가 자신이 선언됐을 때의 환경인 스코프를 기억하여
자신이 선언됐을 때의 환경 밖에서 호출되어도 그 환경에 접근 할 수 있는 함수

const getName = () => {
	const name = "chan";
	const getNameArr = () => {
		return [...name]
	}
	return console.log(getNameArr()); // [ 'c', 'h', 'a', 'n' ]
}
const getName = () => {
	const name = "chan";
	const getNameArr = () => {
		return [...name]
	}
	return console.log(getNameArr()); // [ 'c', 'h', 'a', 'n' ]
}

const callback = getName; // 클로저
callback() // [ 'c', 'h', 'a', 'n' ]

0개의 댓글