Contradiction
JavaScript 는 Number (수), String (문자열), Boolean (불리언), Null, Undefined, Object (객체) 총 6개의 데이터 타입을 가지고 있고, Object 안에는 Array (배열), Function (함수), Date (날짜), RegExp (정규식) 이 포함되어 있습니다.
- #4. Data Type 편 -
Object 는 {} 안에 Property 와 Value 로 구성되어 있는 데이터 타입입니다.
- #9. Object 편 -
위 두 문장을 기준으로 살펴보면 한 가지 모순되는 내용을 발견할 수 있습니다. Object 에 포함되지 않는 String 이 어떻게 length 와 substring() 과 같은 Property 와 Method 를 사용할 수 있는 것일까요? 이번 장에서는 나름 논리적 접근 방식을 통해서 String 이 어떻게 Property 와 Method 를 사용할 수 있는지 하나하나 증명해 나가겠습니다.
인류는 과거부터 현재까지 인간의 기원, 우주의 시작 등 무언가를 규명하기 위해 끊임없이 탐구하였습니다. 모든 생물은 하나의 조상으로부터 기원되었으며, 생존경쟁을 통한 자연 선택에 의해 새로운 종이 형성되어 다양하게 진화했다는 다윈의 종의 기원이 대표적인 예라고 할 수 있습니다. 이러한 다윈의 생물학적 이론은 이후 유전학뿐 아니라 당시 사상과 문화를 이해하는데 큰 영향을 주었습니다.
String 이 어떻게 Property 와 Method 에 접근할 수 있는지에 정답을 얘기하는데 앞서 이들이 어디에 기원을 두고 있는지 살펴볼 필요가 있습니다. 그리고 그 기원을 탐구하는 과정에서 JavaScript 만이 갖고 있는 언어적 특징을 발견할 수 있습니다. 그럼 JavaScript 의 Property 와 Method, 과연 이들은 어디서부터 오는 것일까요?
이 질문에 답을 하기 위해서는 먼저 변수를 선언하는 방식과 _proto_ 에 대해 이해할 필요가 있습니다.
지금까지 우리는 다음과 같은 방식으로 변수를 선언해 왔습니다.
var str = "Hello World";
var num = 10;
var arr = ["apple", "banana", "tomato"];
var func = function (a, b) { return a + b; }; // Function Expressions ( 함수 표현식 )
var obj = { name : "inkwon "};
위와 같은 방법으로 변수를 선언하는 방식을 리터럴 방식이라고 얘기합니다. 이 방법 외에도 다음 방식으로도 변수를 선언할 수 있습니다.
var str = new String("Hello World");
var num = new Number(10);
var arr = new Array("apple", "banana", "tomato");
var func = new Function('a', 'b', 'return a + b');
var obj = new Object({ name : "inkwon "});
이렇게 new 와 String(), Number(), Array(), Function(), Object() 을 함께 사용하여 변수를 선언할 수 있는데, 이것을 생성자 방식이라고 얘기합니다. 여기서 new 는 연산자, String(), Number(), Array(), Function(), Object() 는 JavaScript 데이터 타입 각각의 종의 기원이라고 생각하면 됩니다.
겉으로 보기에 리터럴 방식과 생성자 방식이 비슷해 보이지만, 변수의 데이터 타입을 확인할 수 있는 typeof 로 살펴보면 실제로는 엄청난 차이가 있음을 확인할 수 있습니다.
결과를 살펴보면 같은 "Hello World" 를 입력하였지만 리터럴 방식의 데이터 타입은 "string", 생성자 방식의 데이터 타입은 "object" 가 출력되는 것을 확인할 수 있습니다. 즉, 생성자 방식으로 변수를 선언할 경우 JavaScript 는 변수의 데이터 타입을 Object 로 해석한다는 것을 알 수 있습니다. 그럼 이런 현상을 이해하는 것이 왜 중요한 것일까요?
Primitive Type 인 String 은 리터럴 방식으로 변수를 선언하면 JavaScript 는 자동으로 String() 으로 변환시켜 String() 에서 사용하고 있는 Property 와 Method 에 접근할 수 있게 됩니다.
출처 : MDN - 문자열 원형과 String 오브젝트의 차이
그럼 String() 이 갖고 있는 Property 와 Method 에 접근하고 있다는 증거는 어디서 발견할 수 있을까요? 해답은 바로 _proto_ 안에 있습니다.
생김새, 혈액형, 성격 등 생물의 유전적 정보를 담고 있는 물질을 DNA( Deoxyribose Nucleic Acid )라고 합니다. DNA 는 염색체 중요 구성 물질 중 하나로, DNA 가 갖고 있는 유전적 정보는 다음 세대로 이어져 후손들의 정신적, 육체적 건강에 영향을 미치게 됩니다.
JavaScript 에서 데이터 타입의 DNA 정보를 담는 공간이 바로 _proto_ 입니다. 생성자 방식으로 변수를 선언할 경우 해당 데이터 타입이 어떤 종(?)으로부터 영향을 받고 있는지 _proto_ 을 통해서 확인할 수 있습니다. Reference Type 의 경우에는 리터럴 방식으로 변수를 선언해도 접근할 수 있습니다.
아래 이미지처럼 console.dir() 을 사용하면 변수가 어떠한 구조로 구성되어 있는지 트리 형태로 출력하는데, _proto_ 부분을 살펴보면서 변수가 어느 종의 영향을 받고 있는지 확인할 수 있습니다.
_proto_ 를 클릭하면 String() 이 어떤 Property 와 Method 정보를 갖고 있는지 확인할 수 있습니다.
JavaScript 의 주요 데이터 타입의 기원은 String(), Number(), Array(), Function(), Object() 이 다섯 종족의 능력을 이어받아 사용하고 있다는 것을 _proto_ 를 통해 확인할 수 있었습니다. 보통 위 다섯 종족을 String 객체, Number 객체, Array 객체, Function 객체, Object 객체라고 얘기합니다.
그럼 자바스크립트의 모든 데이터 타입은 Property 와 Method 를 갖고 있는 형태가 되는데, 이것을 전제로 생각한다면 String 과 Number 를 Object 로 봐야 하는 것이 아닌지 내적 갈등(?)이 발생할 수 있습니다.
여기서는 개발자분들마다 얘기가 다르지만... 필자 개인적인 의견으로는 침팬지와 사람의 DNA 구조가 90% 이상 일치한다고 해서 침팬지를 사람이라고 얘기하지 않듯이 String 을 Object 의 특징을 갖고 있다고 해서 Object 로 보기에는 조금은 무리가 있다고 생각됩니다.
이번 장에서는 Property 와 Method 의 기원에 대해서 살펴보았습니다. 이를 어떻게하면 쉽게 설명할 수 있을지 고민의 시간이 길어져 연재가 늦어졌네요. 다른 연재 글과는 다르게 현상이 아닌 본질, 기원에 접근하다보니 쓰다 지우다를 몇번을 했는지 모르겠습니다.
기원이라는 단어 또한 무엇을 기준으로 접근할 것인지에 따라서 의미가 달라질 수 있기 때문에 이점 참고하여 이해해 두시면 좋을 것 같습니다. 다음 연재글은 조금 쉬어가기 위해 조건문에 대해서 살펴보겠습니다.