jQuery 소스코드 분석과 함께하는 자바스크립트 공부 – 3

이 글은 Decoding jQuery series 를 보고 공부한 점을 정리한 글입니다. 원문의 내용과 똑같은 부분도 있고 제가 알고 있는 내용을 따로 덧붙인 부분도 있으니 원문 – Decoding jQuery – OOP and jQuery part 3 을 꼭 보시기 바랍니다.

——————————————————————————————————————–

이전글에서 변수(데이터)와 함수에 대해 설명했습니다. 이제 jQuery의 객체(object)에 대해서 알아보겠습니다.

오늘 알아볼 내용은 prototype입니다. 자바스크립트는 prototype-based language 입니다. 이것이 어떤 의미인지 알아보기 위해 class-based language와 비교를 할 수도 있지만 지금은 그렇게 하지 않겠습니다. 먼저 prototype이 뭔지 알아야 다른 것과 비교가 가능하기 때문입니다. 이제 prototype은 어떤 것이고 jQuery에서 그것을 어떻게 사용하고 있는지 살펴보겠습니다.

1. 모든 함수는 prototype이라는 프로퍼티를 가지고 있습니다. 그리고 prototype은 객체입니다.
우리는 이것을 core.js에서 JavaScript console을 사용하여 테스트 해볼 수 있습니다.
* JavaScript console은 자바스크립트 명령어를 입력하고 실행해 볼 수 있는 일종의 터미널입니다. 파이어버그나 크롬의 개발자도구와 같은 브라우저의 부가 프로그램 형태로 제공되고 있습니다.

var jQuery = function( selector, context ) {
	//...
}
console.log(typeof jQuery.prototype);

// returns object

jQuery의 core.js 내용을 console에 붙여넣고 console.log(typeof jQuery.prototype); 을 실행해보면 object라는 결과가 나오는 것을 볼 수 있습니다. jQuery.prototype은 객체이기 때문입니다.

2. prototype에 메서드와 프로퍼티 추가하기
객체에는 메서드와 프로퍼티를 추가할 수 있습니다. 물론, 값을 수정하거나 삭제하는 것도 가능합니다. jQuery의 prototype 프로퍼티도 객체이기 때문에(jQuery 객체의 프로퍼티이면서 동시에 객체) prototype에 메서드나 프로퍼티를 추가할 수 있습니다.

jQuery.prototype.constructor = jQuery;
jQuery.prototype.init = function( selector, context, rootjQuery ) {
	//...
}

위의 코드는 jQuery.prototype에 constructor 이라는 프로퍼티와 init 이라는 메서드를 추가하고 있습니다. 같은 내용을 아래와 같이 구현할 수도 있습니다.

jQuery.prototype = {
	constructor: jQuery,
	init: function( selector, context, rootjQuery ) {
		//...
	}
}

위 방법은 이전글에서 기본적인 객체에 대해 설명드린 것과 같은 형태입니다. {와 }를 사용해서 객체를 만들고 그 안에 constructor 프로퍼티와 init 메서드를 , 로 구분하여 정의하였습니다. 각각의 프로퍼티의 key와 value는 : 을 사용해서 구분합니다. 객체에 프로퍼티와 메서드를 추가하는 이 두가지 방법은 방법이 약간 다를 뿐 결과는 차이가 없습니다.

3. prototype의 메서드와 프로퍼티 사용하기
prototype은 객체이기 때문에 prototype의 메서드와 프로퍼티는 그냥 jQuery.prototype.constructor, jQuery.prototype.init() 과 같은 형태로 바로 호출해서 사용할 수도 있습니다. 그러나 prototype은 조금 특별한 의미와 쓰임새를 가지고 있기 때문에 이렇게 있는 그대로 사용하기 위해 만든 객체는 아닙니다.

말씀드린 것처럼 prototype은 어떤 함수가 가질 수 있는 프로퍼티입니다. 그런데 자바스크립트에서는 함수로 객체를 만들 수가 있습니다. 객체를 생성하는 용도로 사용되는 함수를 생성자 함수(constructor function)라고 부릅니다. new 키워드와 생성자 함수를 사용하면 결과물로 객체를 리턴받을 수 있는데 이때 그 생성자 함수의 prototype 프로퍼티가 특별한 역할을 하게 됩니다. 먼저 객체를 만들 수 있는 함수인 생성자 함수의 형태를 보면 다음과 같습니다.

var Person = function () {
	this.name = 'person';	// 생성자 함수 안에서의 this 키워드는 이 생성자 함수가 만드는 객체를 가리킵니다.
	this.age = 30;			// 그래서 이 생성자 함수로 생성된 객체는 name 프로퍼티와 age 프로퍼티를 가지게 됩니다.
}

var person1 = new Person();		// new 키워드와 생성자 함수를 사용해서 객체를 만들어서 person1 변수에 할당합니다.

person1.name;	// 'person'
person1.age;	// 30

var person2 = {			// 전에 다뤘던 것처럼 객체를 이렇게 직접 만들 수도 있습니다.
	name: 'person',		// person2 객체는 person1 객체와 프로퍼티, 값이 같습니다.
	age: 30				// 이런 방식으로 만든 객체를 "객체 리터럴" 이라고 합니다.
};

위의 코드에서 생성자 함수를 사용해서 만든 객체인 person1 과 객체 리터럴로 만든 객체인 person2 는 가지고 있는 프로퍼티와 값이 같습니다. 그런데 생성자 함수로 객체를 만들 경우 생성자 함수가 가질 수 있는 프로퍼티인 prototype을 활용할 수가 있습니다.

var Person = function () {
	this.name = 'person';
	this.age = 30;
}

Person.prototype.location = 'Korea';
Person.prototype.hello = function () {
	alert('hello');
}

var person1 = new Person();		// 생성자 함수로 person1 객체 생성

person1.name;		// 'person'
person1.age;		// 30
person1.location;	// 'Korea'	- prototype의 프로퍼티가 생성자 함수로 만들어진 person1 객체의 프로퍼티가 됩니다.
person1.hello();	// 'hello'	- prototype의 메서드 hello가 person1 객체의 메서드가 됩니다.

생성자 함수안에서 직접 프로퍼티, 메서드를 설정하지 않아도 생성자 함수의 prototype의 프로퍼티와 메서드는 생성자 함수로 만들어진 객체의 프로퍼티와 메서드가 되는 것을 보실 수 있습니다. jQuery의 소스코드에 다음과 같은 부분이 있습니다.

new jQuery.fn.init( selector, context, rootjQuery );

jQuery.fn.init 이라는 함수 앞에 new 키워드를 사용한 것으로 보아서 jQuery.fn.init은 생성자 함수일 것입니다. 그리고 new jQuery.fn.init 을 실행한 결과 어떤 객체가 생성되었을 것입니다. 그리고 jQuery의 소스코드에는 다음과 같은 부분도 있습니다.

jQuery.fn.init.prototype = jQuery.fn;

jQuery.fn 을 jQuery.fn.init.prototype 에 할당하고 있습니다. jQuery.fn 은 객체이고 프로퍼티와 메서드들을 가지고 있습니다. 이것을 jQuery.fn.init.prototype 에 할당하여 jQuery.fn.init.prototype 도 jQuery.fn 과 같은 프로퍼티와 메서드를 가지게 하였습니다. 그러면 new 키워드와 jQuery.fn.init 생성자 함수로 만들어진 “객체”는 jQuery.fn.init.prototype 에 있는 프로퍼티와 메서드를 가지게 되므로 결과적으로 이 “객체”는 jQuery.fn 의 프로퍼티와 메서드를 가지게 됩니다. (이 객체는 바로 지역변수 jQuery 입니다. 그리고 나중에 전역변수 jQuery에 할당되게 됩니다.)

복잡하게 느껴지실 수도 있으시겠지만 간단한 원리만 알고계시면 됩니다. 생성자 함수의 prototype의 프로퍼티는 그 생성자 함수로 생성된 객체의 프로퍼티가 된다는 것입니다.

다음글에서는 jQuery.fn, prototype, init 메서드의 관계에 대해서 알아보겠습니다.