2021-07-15
JavaScript 객체지향 프로그래밍
JavaScript 객체 기본
객체는 관련된 데이터와 함수의 집합이다. (프로퍼티와 메소드)
객체는 고유의 패키지에 정보를 안전하게 보호해주는 역할을 한다.
객체 리터럴 방식
var person = {
name: ['Bob', 'Smith'],
age: 32,
gender: 'male',
interests: ['music', 'skiing'],
bio: function () {
alert(
this.name[0] +
' ' +
this.name[1] +
' is ' +
this.age +
' years old. He likes ' +
this.interests[0] +
' and ' +
this.interests[1] +
'.',
);
},
greeting: function () {
alert("Hi! I'm " + this.name[0] + '.');
},
};
var person = {
name: ['Bob', 'Smith'],
age: 32,
gender: 'male',
interests: ['music', 'skiing'],
bio: function () {
alert(
this.name[0] +
' ' +
this.name[1] +
' is ' +
this.age +
' years old. He likes ' +
this.interests[0] +
' and ' +
this.interests[1] +
'.',
);
},
greeting: function () {
alert("Hi! I'm " + this.name[0] + '.');
},
};
객체에 접근하는 방법에는 점 표기법(person.name
)과 괄호 표기법(person['age']
) 이 있다.
this
는 무엇인가?
this
키워드는 지금 동작하고 있는 코드를 가지고 있는 객체를 가리킨다.
Java에서의 this
는 인스턴스 자신(self)를 가리키는 참조변수이다. 주로 매개변수와객체 자신이 갖고 있는 멤버변수명이 같을 경우 이를 구분하기 위해 사용된다.
public Class Person {
private String name;
public Person(String name) {
this.name = name;
}
}
public Class Person {
private String name;
public Person(String name) {
this.name = name;
}
}
하지만 자바스크립트의 경우 Java와 같이 this
에 바인딩되는 객체는 한가지가 아니라, 함수 호출 방식에 따라 달라진다.
- 함수 호출 : 기본적으로
this
는 전역객체에 바인딩 된다. 심지어 내부함수, 메소드의 내부함수, 콜백함수의 경우도 전역객체에 바인딩된다. 1-1. apply/call/bind 호출 : 원하는this
에 바인딩하여 함수를 호출한다. - 메소드 호출 : 메소드를 소유한 객체, 해당 메소드를 호출한 객체에 바인딩된다.
- 생성자 함수 호출 :
- 빈 객체 생성 및
this
바인딩 this
를 통한 프로퍼티 생성- 생성된 객체 반환
- 빈 객체 생성 및
var foo = function () {
console.dir(this);
};
// 1. 함수 호출
foo(); // window
// window.foo();
// 2. 메소드 호출
var obj = {foo: foo};
obj.foo(); // obj
// 3. 생성자 함수 호출
var instance = new foo(); // instance
// 4. apply/call/bind 호출
var bar = {name: 'bar'};
foo.call(bar); // bar
foo.apply(bar); // bar
foo.bind(bar)(); // bar
var foo = function () {
console.dir(this);
};
// 1. 함수 호출
foo(); // window
// window.foo();
// 2. 메소드 호출
var obj = {foo: foo};
obj.foo(); // obj
// 3. 생성자 함수 호출
var instance = new foo(); // instance
// 4. apply/call/bind 호출
var bar = {name: 'bar'};
foo.call(bar); // bar
foo.apply(bar); // bar
foo.bind(bar)(); // bar
OOP
OOP의 기본 컨셉은 실 세계의 일들을 객체를 사용해서 모델링하고, 객체를 사용하지 않으면 어려울 일들을 쉽게 처리하는 것이다.
용어 정리
데이터를 감싸다 : encapsulate 객체를 참조하기 위한 이름 : namespace 추상화 : 중요한 것들만 뽑아서 단순한 모델로 변환하는 작업인스턴스 : 클래스를 통해 만들어진 실제 객체 (클래스는 청사진, 도면, 틀. 인스턴스는 찍어져 나온 결과물) 다형성 : polymorphism. 여러 객체 타입에 같은 기능을 정의할 수 있는 능력
생성자와 객체 인스턴스
- 일반적인 함수를 사용해서 객체 생성: 객체를 만들기 위해 굳이 빈 객체를 만들고내용을 채워서 리턴해야 하는가?
function createNewPerson(name) {
var obj = {};
obj.name = name;
obj.greeting = function () {
alert("Hi! I'm " + this.name + '.');
};
return obj;
}
var salva = createNewPerson('Salva');
salva.name;
salva.greeting();
function createNewPerson(name) {
var obj = {};
obj.name = name;
obj.greeting = function () {
alert("Hi! I'm " + this.name + '.');
};
return obj;
}
var salva = createNewPerson('Salva');
salva.name;
salva.greeting();
- 생성자 함수
new
키워드를 사용하여 함수를 실행하면 다음과 같은 알고리즘이 동작한다.
function Person(name) {
// this = {}; (빈 객체가 암시적으로 만들어짐)
// 새로운 프로퍼티를 this에 추가함
this.name = name;
this.greeting = function () {
alert(`Hi! I'm ${this.name}.`);
};
// return this; (this가 암시적으로 반환됨)
}
var salva = new Person('Salva');
salva.name;
salva.greeting();
function Person(name) {
// this = {}; (빈 객체가 암시적으로 만들어짐)
// 새로운 프로퍼티를 this에 추가함
this.name = name;
this.greeting = function () {
alert(`Hi! I'm ${this.name}.`);
};
// return this; (this가 암시적으로 반환됨)
}
var salva = new Person('Salva');
salva.name;
salva.greeting();
각각은 서로 다른 namespace에 저장되어있다. 객체의 프로퍼티와 메소드들을 사용하려면, person1 또는 person2로부터 호출하여야 한다. 두 객체의 기능은 따로 패키징되어서로 충돌하지 않을 것이다. 그리고 두 Person 객체는 각각 고유의 name 프로퍼티와 greeting() 메소드를 사용할 수 있다. 이 둘이 생성될 때 부여받은 자신의 name 값을사용한다는 것에 주목하자. 이것이 this를 사용하는 매우 중요한 이유 중 하나이다. 객체들은 다른 값이 아니라, 그들이 가진 고유의 값을 사용한다.
객체 리터럴과 생성자 함수 방식의 차이
// 객체 리터럴 방식
var foo = {
name: 'foo',
gender: 'male',
};
console.dir(foo);
// 생성자 함수 방식
function Person(name, gender) {
this.name = name;
this.gender = gender;
}
var me = new Person('Lee', 'male');
console.dir(me);
var you = new Person('Kim', 'female');
console.dir(you);
// 객체 리터럴 방식
var foo = {
name: 'foo',
gender: 'male',
};
console.dir(foo);
// 생성자 함수 방식
function Person(name, gender) {
this.name = name;
this.gender = gender;
}
var me = new Person('Lee', 'male');
console.dir(me);
var you = new Person('Kim', 'female');
console.dir(you);
객체 리터럴 방식과 생성자 함수 방식의 차이는 프로토타입 객체([[Prototype]])
에있다.
객체 리터럴 방식의 경우, 생성된 객체의 프로토타입 객체는 Object.prototype
이다.
생성자 함수 방식의 경우, 생성된 객체의 프로토타입 객체는 Person.prototype
이다
참고자료
JavaScript 객체 소개 함수 호출 방식에 의해 결정되는 this JavaScript: What is the meaning of this?