Developer Factory

[JavaScript] 객체(Object)와 생성자 함수 본문

Developer/Javascript

[JavaScript] 객체(Object)와 생성자 함수

Jeremy.Park 2019. 11. 13. 09:05

출처: https://victorydntmd.tistory.com/51

 

[JS] 객체(Object)와 생성자 함수

2019. 06. 04 수정 1. JS 객체 JS 객체는 다른 객체지향 프로그래밍 언어의 객체와 조금 다른점이 있습니다. 1) prototype 기반의 언어 Java와 C++은 클래스(Class) 기반의 객체지향 언어인 반면, JS는 prototype..

victorydntmd.tistory.com

1. JS 객체

JS 객체는 다른 객체지향 프로그래밍 언어의 객체와 조금 다른점이 있습니다.

 

1) prototype 기반의 언어

Java와 C++은 클래스(Class) 기반의 객체지향 언어인 반면, JS는 prototype 기반의 객체지향 언어입니다.

Class 기반의 객체지향 언어는 class라는 껍데기를 정의하고 이를 통해 객체를 생성합니다.

그러나 prototype 기반의 객체지향 언어는 class 정의 없이도 객체를 생성할 수 있습니다.

물론 생성자 함수를 통해 class를 따라할 수 있는데요, ES6부터는 정식으로 Class가 추가되었습니다.

 

 

2) 캡슐화와 상속 지원

객체지향 프로그래밍에서 중요한 특징 중 하나는 캡슐화와 상속이라는 개념입니다.

JS는 Class가 없어도 클로저를 통해 캡슐화가 가능하고, prototype을 통해 상속이 가능합니다.

( 클로저에 대한 내용은 여기를, Prototype에 대한 내용은 여기를 참고해주세요. )

 

 

3) 프로퍼티와 값의 모임

JS에서 객체는 { }라는 울타리 안에서 프로퍼티와 값을 쌍으로 하는 집합의 모임입니다.

자세한 내용은 앞으로 나올 예제들을 보면서 살펴보도록 하겠습니다.

 

 

 

 

2. 객체 생성 방법

JS에서 객체를 생성하는 방법은 여러가지가 있습니다.

 

1) 리터럴

가장 일반적인 방법은 중괄호{ } 를 사용하여 객체를 생성하는 방법입니다.

var person = {
name: "victolee",
email: "asdf@example.com",
birth: "0225"
}

위와 같이 정의한 person은 name, email, birth 프로퍼티를 갖는 객체입니다.

리터럴 방식으로 객체를 정의할 때는 중괄호{ } 안에 프로퍼티 : 값의 쌍을 입력하고 쉼표(,)로 프로퍼티를 구분합니다.

즉, 프로퍼티와 값의 구분은 콜론(:) 프로퍼티&값 쌍의 구분은 쉼표(,)로 합니다.

( 프로퍼티와 값의 구분은 =이 아닙니다. )

 

프로퍼티의 값으로는 함수가 올 수도 있고, 배열, 객체 등 자유롭게 올 수 있습니다.

리터럴 방식으로 객체를 생성하면 간혹 json라고 오해할 수 있는데요, JS 객체와 JSON은 분명히 다른 것입니다. ( 참고 )

 

 

 

2) Object() 생성자 함수

new 키워드를 이용하여 Object 생성자 함수를 호출하면 비어있는 객체를 얻을 수 있습니다.

var person = new Object();
console.log(person.name)
console.log(person.email)
console.log(person.birth)

person.name = "victolee";
person.email = "asdf@example.com";
person.birth = "0225";
console.log(person.name)
console.log(person.email)
console.log(person.birth)

new Object()를 호출하면 비어있는 객체를 생성합니다.

따라서 객체 생성직후 person 객체에는 name, email, birth 프로퍼티를 갖고 있지 않으므로, new Object()로 비어있는 객체를 생성했으면 프로퍼티를 추가해줘야 합니다.

 

 

 

3) 생성자 함수

생성자 함수를 사용하면 Java나 C++의 Class처럼 껍데기를 만들 수 있습니다.

기존 함수에 new 연산자를 붙여서 호출하면, 해당 함수는 생성자 함수로 동작합니다.

그런데 함수가 일반적인 함수인지 객체를 만들기 위한 목적의 생성자 함수인지 구분하기 위해, 생성자 함수의 첫 문자는 대문자로 표기하는 것이 관례입니다.

function Person(name,email){
this.name = name;
this.email = email;
this.walk = "직립 보행"
}

var person1 = new Person("victolee", "foo@example.com");
var person2 = new Person("worrr", "goo@example.com");

console.log(person1.name + " " + person1.email + " " + person1.walk);
console.log(person2.name + " " + person2.email + " " + person2.walk);

리터럴과 Obejct()로 객체를 생성하는 것과 달리, 생성자 함수를 통해 객체를 생성하면 같은 속성을 가진 객체를 여러 개 생성할 수 있습니다.

즉, person1과 person2 객체는 name, email, walk 프로퍼티를 갖게 되며, 이 방식은 클래스를 통해 객체를 생성하는 것과 유사하죠.

 

또한 생성자 함수에서 정의한 this는 생성자 함수로 생성된 인스턴스가 됩니다.

사실 생성자 함수로 인스턴스를 생성하기 전에, 먼저 비어있는 객체를 생성합니다.

this는 이 비어있는 객체를 가리키고, 그 객체에 name, email, walk 프로퍼티를 추가한 것입니다.

생성자 함수에 반환 값이 없으면 비어있는 객체에 새로운 프로퍼티를 추가한 this가 반환됩니다.

( 조금 더 구체적인 내용을 원하시면 여기를 참고하셔서 Prototype에 대해 알아보시길 바랍니다. )

 

 

일반 함수와 생성자 함수의 차이점은 new 연산자를 붙이느냐의 차이입니다.

생성자 함수인데 new를 붙이지 않는다면 오류를 발생합니다.

이러한 경우를 대비해서 생성자 함수를 호출할 경우 새로운 객체를 만들도록 분기문을 작성하곤 합니다.

function foo(arg){
if(!(this instanceof foo)){
return new foo(arg);
}
this.value = arg ? arg : -99;
}

let a = new foo(10);
let b = foo(100);

console.log(a);
console.log(b);

위의 예제는 변수 b의 경우 생성자 함수 foo를 호출했지만 new 연산자를 붙이지 않은 경우입니다.

foo() 함수를 호출했을 때 this는 전역 객체 window이며, window는 foo의 인스턴스가 아니므로 생성자 함수를 호출하도록 new foo(arg)를 호출하도록 작성한 코드입니다.

 

 

 

 

3. 객체의 프로퍼티 작성, 호출 방법

이전 예제들을 보시면서 객체의 프로퍼티를 작성하는 방법과 호출하는 방법에 대해 자연스럽게 알게되었을 것입니다.

  • 객체의 프로퍼티를 정의하는 방법은 중괄호{ } 내에서 프로퍼티를 작성하면 되고,
  • 객체의 프로퍼티를 호출하는 방법은 객체.프로퍼티로 호출하면 됩니다.

그런데 객체의 프로퍼티를 작성 할 때의 유의사항과 호출할 때 다른 방식이 있어서 이에 대해 다루고자 합니다.

 

1) 프로퍼티 작성시 유의사항

프로퍼티를 정의할 때 작성한 이름은 자동으로 문자열로 취급됩니다.

var person = {
"name" : "victolee",
"email" : "foo@example.com"
}

var person = {
name : "victolee",
email : "foo@example.com"
}

위의 두 객체 선언 방식은 완전히 동일합니다.

 

JS에서 정의한 예약어를 프로퍼티로 사용할 수 있는데요.

예약어를 굳이 바꾸는 것은 좋은 방식은 아니지만, " "으로 예약어로된 프로퍼티를 선언한다면 예약어를 바꿀 수 있습니다.

그래서 저는 주로 " "으로 프로퍼티를 선언하지 않는 편입니다.

 

 

2) 객체의 프로퍼티 이름으로 변수를 사용

let foo = "name"
var person = {
[foo] : "victolee",
"email" : "foo@example.com"
}

console.log(person.name)

프로퍼티 이름에 대괄호[ ]로 덮어주면 변수로 프로퍼티 이름을 작성할 수 있습니다.

 

 

3) 또 다른 프로퍼티 호출 방법

var person = {
name: "victolee"
}

console.log(person.name)
console.log(person["name"]) // victolee
console.log(person[name]) // undefined

보시는 바와 같이 대괄호 [ ]를 사용하여 프로퍼티를 호출 할 수 있습니다.

이 때 대괄호안에는 무조건 문자열이여야 합니다.

 

대괄호에 문자열이 아닌 변수를 넣을 수도 있지만, 그 변수의 값은 문자열이어야 합니다.

var person = {
foo : "name",
name: "victolee"
}

console.log(person["name"])

var nameVar = person.foo
console.log(person[nameVar])

person.foo는 문자열인 "name"을 반환합니다.

"name"이라는 문자열은 변수 nameVar에 할당되고, person의 속성을 호출하는데 사용되는 코드입니다.

어떤 프로퍼티를 호출해야 할지 동적으로 결정해야 할 때 변수에 할당하기도 하므로 기억하두셔야 할 부분입니다.

 

 

 

이상으로 JS 객체에 대해 알아보았습니다.

객체를 생성하는 여러가지 방식이 있고, 객체의 프로퍼티를 선언/호출 하는 방법에 대해 알아보았습니다.