nestJS로 개발 하던 중, 싱글 톤 패턴을 알게 되었고 하나의 인스턴스만 생성하는 것을 알게되었다. 각각의 모듈이 어떤 방식으로 의존성이 주입되어 인스턴스가 생성되는지 연달아 궁금해졌다. JS에서 클래스는 생성자 함수를 활용한다고 알고 있는데, 정확한 작동형태가 머릿속에 그려지지 않았다. 자바스크립트의 객체-함수-클래스의 관계에 대해 탐구해 봐야겠다는 생각이 들었다.
스터디 발표영상 (유튜브)
📺 https://www.youtube.com/watch?v=X9Dtj4crnRM
값
? 말 그대로 '값' 이라서 생각해본적이 없었다.
하지만 정의를 찾아보니,
자바스크립트에서는 표현식
이 평가
된 것을 값으로 정의했다.
그럼 표현식은 뭔데?
평가
는 뭐고 문
은 정확히 무엇을 의미하는가..문
은 문법적으로 뜻을 지니는 (더이상 쪼갤 수 없는) 문장/식 이고,
평가
는 그 문장/식이 계산되어서 메모리에 저장되는 것을 의미했다.
사실 비슷한 단어가 계속 반복되서 말장난 하는 것 같지만, 구조를 그려보면 다음과 같다.
문
이 있고, 평가 가능여부에 따라 나뉜다.평가가 불가능한 문
은 선언문, 반복문, 조건문 등이 있고,평가가 가능한 문
이 우리가 말하는 표현식
인 것이다.표현식
은 평가가 가능한 문이므로, 평가를 하면 비로소 값
이 된다.'abc'라는 표현식이 평가될 때,
메모리에 a 변수가 할당되고, undefined로 초기화가 된다.
그 후, 'abc'를 넣은 메모리의 주소를
a로 할당(=) 하며 주소값을 가지게 된다.
즉, a(라는 식별자가 붙은 변수)가 가리키는 것은 'abc'이다.
그러면 1,2,3 이나 'abc' 같은형태가 아닌, 자료구조는 어떻게 될까.
객체를 담기 위한 메모리를 지정하고, 객체안에 있는 변수들(name, age)이 담길 메모리도 지정해 준다.
객체가 담길 메모리에는 최종적으로 객체의 주소범위만 담기게 된다.
b가 가리키는 것은 객체 자체가 아닌, '객체를 가리키는 주소의 값' 이 된다.
잘 생각해보면 어렵지 않다. 자료구조는 상자 안에 상자가 있는 형태니, 저런식으로 주소를 꼬리에 꼬리를 무는 형태가 되는게 당연하다.
a는 'abc'를 가리켰는데,
b는 @7104 주소를 가리킨다.
똑같이 var ###
= 000
형태로 할당했는데
변수가 가리키는 값의 형태가 다르다.
원시타입
인 것과 그 외 주소타입
로 표현된 것.객체타입
(참조타입) 이라고 하게 된 것이다.처음 그렸던 구조도에 방금 것을 추가해 보면,
객체가 어떤 위치에서 등장했는지 파악할 수 있다.
이제 함수를 보자.
표현식
으로 사용될 수 있다는 것이다.표현식
은 평가가 되어 값 이 되는 존재였다.함수
는 객체타입
이라고 할 수 있다.함수는 자바스크립트가 설계 될 때 일급객체로 취급되도록 되어있다. 4가지 조건을 만족하면 일급객체라고 하는데,
함수의 결과 값만 일급으로 다루는게 아니라, 함수 그 자체를 일급으로 다룬다는 점이 중요하다.
함수 내부에는 [[call]]
이라는 내장메서드가 포함되어 있는데, 이 메서드는 일반 객체에서는 존재하지 않는다. 함수가 호출 될 때 사용되는 장치이다.
즉, 객체 중에서 호출이 가능
한 존재들을 모아 분류한 것이 함수
이다.
함수가 일반객체와 구분되는 것은 다양한 것들이 있지만, 일단 함수를 이렇게 가지치기를 할 수 있구나 라고 생각하면 된다.
(실제로 함수가 생성될 때는, Funcion 생성자 함수에 의해 생성되며, 이는 다른 생성자로 만들어진 객체들과 내장된 내용이 다르다.)
여기까지 함수가 어떤 부류인지 알아보았다.
이어서 클래스를 보자.
인스턴스
)는 생성자 함수로부터 만들어지며 (리터럴로 만들어도 암묵적으로 생성자 함수를 통해 구현된다)프로토타입
을 가져서 부모의 프로퍼티를 참조할 수 있다.생성자 함수
와 프로토타입
은 1:1의 상호 참조구조를 갖는다.prototype
은 무엇인가?[[prototype]]
과는 다른 존재인 것 같은데..저 삼각형의 구조를 하나 더 그려보면 쉽게 알 수 있다.
생성자 함수로 만들어진 함수가, '또 다른 어떤 인스턴스' 의 생성자 함수가 될 때, 사용되어야 할 프로토 타입 객체인 것이다. (빨간색 표시)
여기서 알 수 있는 것은,
" 생성자 함수
는 함수
에 포함된다. " 보단,
" 모든 함수
는 잠재적 생성자 함수
" 라는 것이 더 정확한 표현이다.
(단, 내부에 [[construct]]
가 있어야만 함)
예시를 보자.
원을 만들어 내는 함수를 정의했다.
반지름이 있고, 지름을 구하는 함수가 내포되어 있다.
인수를 전달하여 new 로 인스턴스를 생성할 수 있다.
나는 생성자 함수를 만든 것이 아니라,
함수를 만들어 두고, new를 붙여서 생성자 함수로 활용한 것이다.
< 참고 >
생성자 함수
로 사용될 때의 this 는 새로 생성하는 객체를 가리킨다.
위 처럼 생성자 함수로 new Circle(5) 를 하면, 새로운 Circle 인스턴스의 반지름이 5 가 된다.- 반면에
일반 함수
로 실행한다면 this는 참조하는 객체가 없으므로 전역객체를 가리키게 된다.
따라서 그냥 Circle(5)를 해버리면 전역변수 radius가 생성되고 그 값이 5가 되어버린다.
아까 보았던 삼각형 구조에서, 초록색 부분이 클래스가 되는 것이다.
클래스를 만들고 내부를 보면,
typeof는 function으로 나오며,
프로퍼티로 prototype 객체를 가지고 있다.
실제로 클래스가 평가 될 때에도, 생성자 함수 형태로 평가가 된다.
클래스의 모든 역할을 생성자 함수로 구현이 가능했다.
클래스는 사실 자바스크립트에서 필요없는 것 처럼 보이기도 한다.
클래스 작동원리를 파헤쳐 보면, 모두 프로토타입 형태로 구동된다. (ex : 상속 -> 프로토타입 체인 )
다만 객체지향의 직관성을 높여서 간결하고 명료한 코드작성을 가능하게 한다.
결국 클래스는 생성자 함수의 다른 형태라고 보면 되겠다.
문
에서 부터 시작한 구조를 클래스
까지 그려보면 위와 같다.표현식
이라고 하며, 표현식은 평가가 되면 값
이 된다.값
은 참조하는 데이터의 유형에 따라 원시값
과 객체
로 분류된다.객체
는 호출여부에 따라 일반객체
와 함수
로 나뉜다.생성자 함수
를 다른 형태로 표현한 것이 클래스
이다.
따라서 클래스
는 함수
다.
그리고 함수
는 객체
다.
끝.