티스토리 뷰


* 이번에는 저번에 만들었던 틀에서 사용했던 연관배열과 prototype에 대해서 공부해보도록 하자.


2012/10/04 - [Programming Lecture/Javascript Library] - [자바스크립트 라이브러리 만들기] 1. 개요

2012/10/04 - [Programming Lecture/Javascript Library] - [자바스크립트 라이브러리 만들기] 2. 시작 - 사전조사 및 설계

2012/10/11 - [Programming Lecture/Javascript Library] - [자바스크립트 라이브러리 만들기] 3. 기본 지식 - 모듈과 네임스페이스

2012/10/15 - [Programming Lecture/Javascript Library] - [자바스크립트 라이브러리 만들기] 4. 실전 1 - 모듈과 틀 만들기



*연관 배열

: 우선 연관 배열(associative array) 또는 object literal이라고도 하는 표현 방식은 네임스페이스 안에 함수들을 어떠한 특정 object의 멤버 변수로서 저장하고 있는 형태이다. 즉 예를 들면, 아래 소스와 같이 함수를 부여한 것이 연관 배열을 이용해서 함수를 부여한 것이다.


	var utree = {
		makeTree : function(_container_id , _tree_name) {
			//implement : return the generated tree
			//여기에서 this.yourFunction()를 쓴다면?
		},
		getTree : function(_tree_name) {
			//implement : return the tree according to the tree name
		},
		yourFunction : function() {
			//utree의 다른 함수에서 호출하고 싶은 함수
		}
	};
	window.utree = utree;


다음과 같이 함수를 부여하는 경우, 함수는 처음에 한번 생성되고나서 레퍼런스를 하나만 가지고 있게 된다. 이렇게 선언한 것의 장점은 함수를 어떠한 object의 멤버함수처럼 사용을 할 수 있지만, 그 object는 new와 같은 어떠한 초기화의 단계를 거치지 않고 바로 쓸 수 있다는 점이다. 이것이 연관배열을 이용하는 것과 아래의 prototype으로 함수를 선언하는 것의 가장 큰 차이일 것이다.


하지만 역시 단점도 있다. 바로 자바스크립트의 애매모호한 scope개념 때문에 this가 수시로 바뀌게 된다. 즉, utree.makeTree함수를 호출하게 되면 어디서 호출하게 되느냐에 따라 this가 달라질 수 있다는 것이다. 기본적으로는 현재 utree 오브젝트의 상위 함수, 즉 가장 밖을 둘러싸고 있는 (function(){ ... })(); 이 함수를 가리키고 있고, this가 변경되는 일은 특히 이벤트 콜백함수에서 빈번하게 일어나므로 이러한 경우는 utree 를 선언하는 function scope 안에 변수를 선언해서 사용하는 방법이 있다.


원래 함수의 목적과는 다른 예이지만 this가 바뀌는 경우가 발생하는 예를 들자면 


button.addEventListener("click" , utree.makeTree);


이렇게 함수를 호출하게 된다면 utree.makeTree() 함수 안에서 this는 바로 위의 이벤트 리스너를 추가한 button을 가리키게 된다. 자바스크립트 만의 독특한 특징이니 자바스크립트를 처음 접하는 c,java 개발자들을 이러한 것 때문에 곤욕을 치룰 수 있을 것이다. 그래서 소스 코드를 다시 보면


var utree = {
		makeTree : function(_container_id , _tree_name) {
			//여기에서는 utree.yourFunction()를 쓰자
		}, //중략
		yourFunction : function() {
                    //여기서 뭔가를 하겠죠
		},
};


이렇게 utree가 생성되는 scope의 상위 scope에 변수를 하나 둬서, makeTree 함수 안에서는 this를 사용하지 말고, utree.yourFunction() 이런식으로 사용하면 된다. this의 행방을 찾는 것보다는 이러한 식으로 scope 밖에 변수를 선언해놓고 캐쉬처럼 사용하는 것도 편한 방법이다.




* prototype을 통한 함수 부여

: 그 다음은 prototype을 통한 함수 부여이다. prototype의 사용법은 이전의 소스코드에서 살짝 살펴보면 아래와 같다.



	var Tree = function(_container) {
		this.container = _container;
		this.root = null;
		this.nodeMap = {};
	};

	Tree.prototype.addNode = function(_parent_id , _value , _id , _type) {
		//implement
		return this;
	}

	Tree.prototype.removeNode = function (_id) {
		//implement
		return this;
	}


이것은 마치 헤더파일이 빠진 c를 보는듯한 기분이다. 기존에는 오브젝트(클래스) 안에 함수를 선언하는 방법이 있었는데, 아래와 같이했었다.


	var Tree = function(_container) {
		this.container = _container;
		this.root = null;
		this.nodeMap = {};
		this.addNode = function (_parent_id , _value , _id , _type) {
			//implement
		}
		this.removeNode = function (_id) {
			//implement
		}
	};


위와 같이 하는 것은 외관상 prototype과 똑같다. 하지만 각각 사용해야할 때는 다르다. 아래와 같이 하는 경우 한번 new Tree를 하는 경우 그때마다 새로운 this.nodeMap과 this.addNode가 생긴다. 하지만 prototype을 사용하게 되는 경우에는 prototype에 있는 함수 하나를 여러 개의 객체들이 같이 사용을 하게 된다. 즉, 특정 클래스의 엄청나게 많은 수의 객체를 사용하게 된다면 prototype을 사용하는 것이 메모리 사용상 유리하다. 속도적인 면에서도 prototype을 이용하는 것이 this를 사용하는것보다 약 10%~20%정도 빠르다고 하지만, 그렇게 큰 차이로 치지는 않아도 될 것이다.


그렇다면 this를 써야할때에는 언제인가? 바로 closure를 이용해서 local private 변수를 이용하고자 할 때이다. 사실 이러한 용도로 사용하게 될 일은 매우 적을 것이지만, 서버측에서만 변경해야하는 값인 경우 local private으로 변수를 생성하면서 this를 사용하면 함수에서 접근을 할 수 있다. prototype의 가장 큰 단점은 이러한 식으로 local private에 접근할 수 있는 방법이 없다는 것이다. 예를 들면, Tree안에 누가 트리를 만들었는지 권한을 주고 싶다면 외부에서 받아서 private으로 두는 것이 좋을 것이다. 그럼 아래와 같이 하면 된다.


	var Tree = function(_container) {
		this.container = _container;
		this.root = null;
		this.nodeMap = {};

		var owner = "root";
		this.addNode = function (_parent_id , _value , _id , _type) {
			//implement
		}
		this.removeNode = function (_id , currentUser) {
			if(currentUser === owner){/* do something */};
				//현재 사용자가 owner라면 지운다
		}
	};


위와 같은 경우 tree의 owner가 root일 때 root 이외에는 지우는 권한을 주지 않겠다는 것이다. 이 때 로컬 변수로 선언한 owner는 외부에서 바꿀 수 없기 때문에 이러한 경우는 this.func = function(){}; 과 같은 식으로 멤버 함수를 선언하는 것이 유용하다. 하지만 이미 모든 것이 공개되어있는 웹에서 private을 쓰는 경우는 흔치 않으므로 잘 생각해서 구분하면 된다.


따라서 prototype과 this는 필요한 경우에 따라서 유연하게 바꿔가면서, 혼용해서도 활용이 가능하지만, 특별한 경우가 아니라면 prototype을 쓰는 것이 유리하다는 것을 알 수 있다.



* 연관 배열과 prototype?

: this와 prototype의 사용처는 공부했는데, 연관 배열과 prototype은 언제 사용하는 것이 좋을지 생각해보자. prototype은 클래스를 생성할 때 사용하는 것이고, 연관 배열은 함수만 호출하는 오브젝트를 만들 때 사용하면 된다.


쉽게 말하자면, 만약에 어떤 함수를 클래스처럼 여러 개 생성하고자 한다면 prototype(또는 this)를 이용하면 되고, 시작하자마자 한번 생성되서 그 오브젝트의 함수만 호출하는 용도라면 연관 배열을 쓰면 될 것이다. 또 다른 관점으로 보자면 라이브러리라면(위에서 utree) 연관 배열을 사용하면 되고, 라이브러리를 통해 여러번 생성될 수 있는 다른 객체라면(Tree 또는 Node) prototype을 사용하는 것이 좋을 것이다.



* 기본지식은 여기까지만 알아도 충분히 자바스크립트 라이브러리를 만들 수 있을 것이다. 다음에는 실제로 함수들을 하나씩 구현해보면서 나오는 어려움들을 고민해보자.


끝.

공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
«   2024/03   »
1 2
3 4 5 6 7 8 9
10 11 12 13 14 15 16
17 18 19 20 21 22 23
24 25 26 27 28 29 30
31
글 보관함