객체 기초
객체(Object)는 JavaScript 뿐만 아니라 객체지향적(Object-Oriented) 성격을 띄는 모든 프로그래밍 언어에서 중요한 개념입니다. 객체는 "세상에 존재하는 것"—도로 위를 달리는 자동차, 탁상 위에 놓인 컵, 심지어 귀여운 고양이—을 프로그래밍 언어로 표현한 것과 같습니다.
위에서 언급한 "세상에 존재하는 것"은 그 자체로 정보를 가지기도 하고, 특정한 행동을 하기도 합니다. 고양이를 예로 들어봅시다.
고양이에 관한 정보로는 성별, 묘종, 털의 색, 눈동자 색 등등이 됩니다. 이를 JavaScript에선 고양이의 프로퍼티(Property)라고 합니다.
한편, 고양이는 우아하게 걷거나, 높이 점프하거나, 높은 곳에서 안전하게 착지하는 행동을 보입니다. 이를 고양이의 메소드(Method)라고 합니다.
정리하자면, 객체가 담고 있는 정보를 프로퍼티, 객체가 할 수 있는 행위를 메소드라고 부릅니다. 이전에도 알아봤듯이, 데이터는 변수에 저장하고 특정 기능을 위한 코드는 함수를 선언해 저장했습니다. 프로퍼티는 객체가 가지는 변수, 메소드는 객체가 가지는 함수로 볼 수 있습니다.
객체 선언
객체를 선언하는 방법은 다양하지만, 그 중 가장 자주 쓰이는 방식인 객체 리터럴을 알아보겠습니다. 객체 리터럴은 중괄호를 사용한 방식입니다.
let obj = { str: "value1", num: 34, bool: true, add: function(a, b) { return a + b; } minus: (a, b) => (a - b); };
객체는 키(key)와 값(value)의 쌍으로 이루어집니다. 위 코드에서 str
, num
, bool
은 obj
객체의 프로퍼티입니다. add
, minus
는 키에 할당한 값이 함수이므로 obj
객체의 메소드입니다.
접근
객체의 프로퍼티 또는 메소드에 접근하는 방법으로 두 가지가 존재합니다.
점(.)을 이용한 접근
첫 번째 방법은 점(.
)을 이용한 접근입니다. 객체와 키를 점으로 구분해 객체.프로퍼티
와 같이 사용합니다. 메소드를 호출하는 방법은 객체.메소드()
와 같습니다.
let cat = { name: "Nabi", sexual: "female", breed: "ragdoll", jump: (height) => `Jump ${height}m!` }
위 객체에서 name
프로퍼티에 접근하고자 할 경우 아래와 같이 작성합니다.
cat.name; // "Nabi"
메소드에 접근하는 방식도 동일합니다. jump
메소드에 접근하고자 할 경우
cat.jump(95); // "Jump 95m!"
와 같이 작성합니다. 메소드는 함수이므로 메소드의 호출은 함수의 호출 방식과 동일합니다.
대괄호([])를 이용한 접근
두 번째 방법은 대괄호([]
)를 이용한 접근입니다. 앞서 알아본 바와 같이 배열의 특정 요소에 접근하기 위해 대괄호를 사용했습니다.
const arr = [1, 2, 3]; arr[1]; // 2
객체도 유사하게 접근할 수 있습니다. 대신, 객체는 대괄호 안에 인덱스 대신 찾고자 하는 값에 대응하는 키를 문자열로 입력합니다.
let cat = { name: "Nabi", sexual: "female", breed: "ragdoll", jump: (height) => `Jump ${height}m!` }
위 객체에서 name
프로퍼티에 접근하고자 할 경우 아래와 같이 작성합니다.
cat["name"]; // "Nabi"
이러한 방법은 몇몇 상황에서 더 유용합니다. 변수에 할당된 문자열을 키로 사용할 수도 있습니다.
const key_name = "name"; cat[key_name]; // "Nabi"
할당
객체의 프로퍼티 또는 메소드에 접근하는 방법을 이용해 값을 할당할 수도 있습니다. 변수에 값을 할당하는 것과 동일하게 대입 연산자 =
를 사용합니다.
cat.name = "Cheese"; cat["sexual"] = "male"; cat.jump = (height) => `Jump ${height * 100}m!`;
this: 객체 자신을 참조하기
객체를 공부하며 계속 다루었던 cat
객체에 고양이의 정보를 메시지로 보내는 메소드를 추가하고자 합니다.
let cat = { name: "Nabi", sexual: "female", breed: "ragdoll", jump: (height) => `Jump ${height}m!`, sendInfo: () => { msg.reply(`name: ${this.name}\nsexual: ${this.sexual}\nbreed: ${this.breed}`); } }
sendInfo
메소드를 구현할 때 this
키워드를 사용했습니다. this
는 현재 속한 객체, 즉 cat
객체를 가리킵니다. this
키워드를 사용해 현재 속한 객체의 다른 프로퍼티나 메소드에 접근할 수 있습니다.
모든 것은 객체였습니다
JavaScript의 거의 모든 것은 객체입니다. 여기서 '모든 것'이라는 건, 여태 사용해온 거의 모든 값을 말합니다.
예를 들면 문자열, 숫자, 불리언 등이 있습니다. 문자열은 String
객체, 숫자는 Number
객체, 불리언은 Boolean
객체입니다.
최근에 알아본 배열, 함수 또한 사실은 각각 Array
객체와 Function
객체입니다. 이 말인즉슨, 우리는 여태 JavaScript를 공부하며 객체를 만들어내고 사용해왔다는 의미입니다.
문자열 값을 보겠습니다.
"Hello, World!"
자주 사용한 문자열 리터럴입니다. 이는 String
객체를 생성하는 방법 중 하나였던 것입니다. String
객체엔 includes
라는 메소드가 존재합니다. 어떤 문자열에 특정 문자열이 포함되어 있는지의 여부를 불리언으로 반환합니다.
"Hello, World!".includes("World"); // true
더 직접적인 예를 들어보겠습니다. 이전에 배열 편에서 배열이 가지는 요소의 개수를 구하기 위해 length
를 배웠습니다.
let arr = ["Seoul", "Incheon", "Busan", "Daejeon"]; arr.length; // 4
여기서 length
는 Array
객체의 프로퍼티입니다. ["Seoul", "Incheon", "Busan", "Daejeon"]
는 배열 리터럴을 이용해 Array
객체를 생성한 것입니다.
이제 거의 모든 것이 객체였다는 사실을 실감할 수 있을겁니다. 이것이 JavaScript를 공부할 때 객체를 꼭 알아야 하는 이유입니다. 객체는 객체 지향 프로그래밍의 핵심이 되는 개념이므로 이를 잘 알아두면 다른 프로그래밍 언어를 공부할 때도 어려움이 덜할 수 있습니다.