클래스 기반 객체지향 프로그래밍 언어(Java, C++ 등)는 객체 생성 이전에 클래스를 정의하고 이를 통해 객체(인스턴스)를 생성하지만, 프로토타입 기반 객체지향 프로그래밍 언어는 클래스 없이 객체를 생성할 수 있다.
자바스크립트의 모든 객체는 자신의 부모 역할을 담당하는 객체와 연결되어 있으며, 객체 지향과 같이 부모 객체의 프로퍼티나 메서드를 상속받아 사용할 수 있다. 이러한 부모 객체를 프로토타입(프로토타입 객체)이라고 한다.
프로토타입 객체는 생성자 함수에 의해 생성된 각각의 객체에 공유 프로퍼티를 제공하기 위해 사용한다.
자바스크립트의 모든 객체는 [[Prototype]]
이라는 인터널 슬롯을 가지고 있는데 이 슬롯의 값은 Prototype 객체이며, __proto__
accessor property로 접근할 수 있다.
모든 객체는 자신의 프로토타입 객체를 가리키는 [[Prototype]]
internal slot을 갖고 있으며 상속을 위해 사용된다.
함수도 객체이므로 [[Prototype]]
인터널 슬롯을 갖지만, 함수 객체는 일반 객체와는 달리 prototype 프로퍼티도 소유하게 된다.
prototype 프로퍼티는 프로토타입 객체를 가리키는 [[Prototype]]
인터널 슬롯과 다르다.
function Person(name) {
this.name = name;
}
const foo = new Person('Lee');
console.dir(Person); // prototype 프로퍼티가 있다.
console.dir(foo); // prototype 프로퍼티가 없다.
[[Prototype]]
: 함수를 포함한 모든 객체가 가지고 있는 인터널 슬롯으로, 객체 입장에서 자신의 부모 역할을 하는 프로토타입 객체를 가리키며 함수 객체의 경우 Function.prototype
를 가리킨다.자바스크립트는 특정 객체의 프로퍼티나 메서드에 접근하려고 할 때, 해당 객체에 접근하려는 프로퍼티 또는 메소드가 없다면 [[Prototype]]
이 가리키는 링크를 따라 자신의 부모 역할을 하는 프로토타입 객체의 프로퍼티나 메소드를 차례대로 검색하는 구조
함수 정의 방법 (아래 세가지 방식 모두 Function() 생성자 함수로 함수 객체를 생성한다.)
객체 리터럴 방식이나 생성자 함수 방식이나 결국 모든 객체의 부모 객체인 Object.prototype
객체가 프로토타입 체인의 종점이 된다. (프로토타입 체인을 타고 올라갔을 때 마지막 지점)
객체의 프로퍼티를 참조할 때 해당 객체에 프로퍼티가 없는 경우, 프로토타입 체인이 동작한다.
원시 타입 문자열과 String() 생성자 함수로 생성한 문자열 객체의 타입은 다르다.
원시 타입은 객체가 아니므로 프로퍼티나 메소드를 가질수 없지만, 원시 타입으로 프로퍼티나 메소드를 호출할 때 원시 타입과 연관된 객체로 일시적으로 변환되어 프로토타입 객체를 공유하게 된다.
스코프(scope)란, 식별자의 유효범위를 의미한다.
전역 스코프 (Global scope) : 코드 어디에서든지 참조할 수 있다.
지역 스코프 (Local scope or Function-level scope) : 함수 코드 블록이 만든 스코프로 함수 자신과 하위 함수에서만 참조할 수 있다.
전역 변수 (Global variable) : 전역에서 선언된 변수이며, 어디서든 참조 가능하다.
지역 변수 (Local variable) : 지역(함수) 내에서 선언된 변수이며, 해당 지역과 그 지역의 하위 지역에서만 참조 가능하다.
변수는 자신이 선언된 위치를 기준으로 스코프를 갖는다.
전역에 변수를 선언하면 이 변수는 어디서든지 참조할 수 있는 전역 스코프를 갖는 전역 변수가 된다.
전역 변수를 사용하면 변수 이름이 중복될 수 있고, 의도치 않은 재할당에 의한 상태 변화로 코드를 예측하기 어려워지므로 남발해선 안된다.
최소한의 전역변수 사용
var MYAPP = {};
MYAPP.student = {
name: 'Lee',
gender: 'male'
};
console.log(MYAPP.student.name);
(function () {
var MYAPP = {};
MYAPP.student = {
name: 'Lee',
gender: 'male'
};
console.log(MYAPP.student.name);
}());
console.log(MYAPP.student.name);
자바스크립트는 함수를 어디서 정의했는지에 따라 상위 스코프를 결정하고 이를 렉시컬 스코프(정적 스코프)라 한다.
함수의 호출 위치는 함수의 스코프 결정에 영향을 주지 못한다.