Javascript_base - 해당되는 글 8건
오늘은 제목에서 밝힌 것처럼 저러한 내용에 대해서 이야기 해보려합니다.

OOP! 이것은 무엇일까요? 그리고 자바와같은 언어에서의 OOP와 JS에서의 OOP는 어떻게 다른걸까요?

다들 아시다시피 OOP는 컴퓨터친화적이 아닌 인간친화적입니다. 즉, 개발의 방법의 주체를 컴퓨터에 맞추지 말고, 만드는 사람인 인간에게 맞춰 개발하자는 것이지요. 여러분은 한번쯤 이러한 고민을 해보시지 않으셨나요?
개념은 이러한데 과연 JS에서 OOP란 무엇인가...

그에 대한 여러분들의 의견을 듣고싶습니다.

posted by blankus
태그 - javascript, OOP
Javascript_base  |  2007/12/12 15:45
오늘은 무지 추운날입니다 ㅠㅠ

세상을 위해서는 겨울이 더욱 추워져야 하는데 저를 생각하면 날이 따스했으면 합니다. 어제 다큐멘터리를 보는데 지구의 온난화때문에 많은 자연의 재앙들이 생긴다고 하더라구요. 걱정입니다

오랜만에 기초강좌를 올려보려고 합니다. 순서에 맞지는 않다고 보여집니다만..^^ 제목처럼 데이터타입들에 대해서 알아보려고 합니다. 많은 분들이 잘 알고계신 부분이지만 놓치면 후회(?)할 부분도 있으니까 이부분을 너무 저평가하여 생각하시면 안됩니다. 저도 사실 많은부분을 할애한 부분이기도 합니다.

상세한 부분을 알아보기 전에 전체적인 그림을 그려보도록 하겠습니다.
여러분은 데이터타입에 대해서 잘알고 계신가요? 자바스크립트에서 사용하는 데이터타입은 크게 세가지로 나눌 수 있습니다. 원시타입(primitive datatype), 단순타입(trivial datatype), 혼합타입(composite)이 그것입니다. 다시 원시타입은 Number, String, Boolean으로, 단순타입은 null과 undefined으로, 혼합타입은 Object입니다. 우리가 흔히들 사용하는 function, array등은 모두 Object에 해당됩니다. 나중에 알아보겠지만 Object와 Array는 좀 특별한 내용이 있습니다. 그리고 프로그램을 하다보면 자주 접하게 되는 By value와 By reference의 차이점에 대해서도 알아볼 것이고, Wrapper에 대해서도 알아볼겁니다.

자 이제 전체적인 그림을 그려봤으니 자세하게 알아보도록 하겠습니다.

Number
다른 언어에서는 Integer와 floating-point를 따로 구분해서 사용하고 있습니다. 허나, 자바스크립트에서는 따로 구분하지 않습니다. 쉽게 var num = 10 도 되지만 var num = 3.14 도 된다는 이야기지요. 앞선 예제처럼 직접적으로 숫자를 사용하는 것을 numeric literal이라고 부릅니다. Number는 3가지의 Literals를 가집니다.
  1) Integer Literals : 다들 아시다시피 10진수 기반의 모든 숫자를 이야기합니다.
  2) Hexadecimal 과 Octal Literals :  16진수(ex : 0xff or 0Xff)와 8진수(ex : 0377)를 사용하는 number입니다
  3) Floating-point Literals : 소수점을 사용하는 number입니다. 형식은 [digits][.digits][(E|e)[(+|-)]digits]입니다.
위의 예제는 따로 구성하지 않겠습니다. 뒷편에 조금씩 다룰것이니까요 ^^
혹시 여러분들은 Number.MAX_VALUE / Number.MIN_VALUE를 아시나요? 혹시 파이어버그를 사용하신다면 console창에 한번 찍어보세요. 자바스크립트에서 사용할 수 있는 최대/최소값을 알려줍니다. 그리고 isNaN()이라는 함수가 있습니다. 숫자인지 판별하여 그값을 boolean형태로 돌려줍니다. isFinite()라는 함수는 주어진 값이 Number.MAX_VALUE 또는 Number.MIN_VALUE 사이에 값이 존재하는지의 여부를 boolean형태로 알려줍니다.

String
프로그램을 짜면서 가장 많이 사용되는 데이터타입이 아닐까 합니다. String literal은 원칙적으로 한줄에 써야하는건 아시죠? ㅎㅎ String literal에 대해서는 특별한건 없구요 한번 집어보는 정도로만 하겠습니다.
여러분들은 숫자를 문자로 어떻게 변경(converting)하시나요? 보통 toString()을 많이 사용하시죠? 네 그렇습니다. 저도 그렇지요 ㅎㅎ 그렇다면 아래의 예제를 보세요.

var n = 123456.789;
n.toFixed(0) // "123456"
n.toFixed(2) // "123456.78"
n.toExponential(1) // "1.2e+5"
n.toExponential(3) // "1.235e+5"
n.toPrecision(4) // "1.235e+5"
n.toPrecision(7) // "123456.8"

평소에 사용해본 적이 있으신 함수인가요? 중요한건 아닙니다. 이런것도 있다~ 정도만 아시면 되겠습니다. 그래도 실제로 한번씩은 실습을 해보시기 바랍니다.

그렇다면 반대로 문자를 숫자로 변경(convertin)을 해보셨나요? 어떤 방법을 사용하시나요? 보통은 아래처럼 사용합니다.

var num = Number(string_value)  또는 var num = parseInt(string_value)
둘의 차이점을 아시나요? 다음의 예제를 보시죠

var txt = "3 blind mice"
var num_1 = Number(txt)
var num_2 = parseInt(txt)

num_1과 num_2의 값을 예상하시나요? 네~ num_1은 undefined이고 num_2는 3이 나옵니다. 직접해보세요 ㅎㅎ 그렇다면 아래의 경우는 어떨까요?

var txt = "3.14입니다"
var num = parseInt(txt)
답은 3입니다. 너무 쉬웠나요? ㅎㅎ 답은 parseIntInt에 있습니다. Int는 Integer의 약자이고 앞에서 Integer는 10진수를 기반으로 한다고 했습니다. 하지만 이것은 기본값이구요, 만약 parseInt("11", 2)라고 한다면 답은 3이 됩니다. 왜냐하면 11이란 값을 2진수의 값으로 변경하기 때문입니다. 그리고 한가지 팁아닌 팁을 알려드리면,

var txt = "$72.34"
var num = parseInt(txt) // return NaN

입니다. ^^ 자세히 설명하지 않아도 느낌이 오셨을거라 생각합니다.

오늘은 여기까지하고 다음 강좌는 Boolean 데이터타입부터 하겠습니다.
좋은밤 되세요 ㅎㅎ

posted by blankus
Javascript_base  |  2007/11/18 21:40

아래의 글을 읽으신 분은 아시겠지만, 어제 시시회 당첨영화를 보러갔드랬습니다. "뜨거운 녀석들" 제목부터가 별로 맘에 안들었습니다. 영화가 시작하고 조금후부터 사람들이 한둘씩 나가더군요.. 영화를 끝까지 보고
나왔습니다. 후회가 되었습니다. 나도 진작 나올껄 ㅠㅠ
도대체 돈이 얼마나 남길래 저런영화를 만드는 겁니까? 그런돈 있음 불우이웃을 좀 도와주세요 네???

오늘은 저번 강좌에 이어 클로져에 대해서 이어가겠습니다. 클로져에 대해서 개념이 안잡히신 분들을 위해
간략하게 정리하겠습니다.

함수안에 존재하는 지역변수는 지역변수로써 살아야하며, 함수가 죽으면 따라죽을 운명인데, 클로져는 죽어
마땅한 함수의 지역변수를 밖으로 끄집어내어 영역을 변경(확장)하는 것
을 의미합니다. 물론 이한줄이 클로져를 전부 나타낼 수는 없습니다. 하지만 전 이렇게 설명하려 합니다. 다르게 설명해봤자 서로 헛깔릴게 분명
하거든요 ^^ 사람이든 변수이든 자기의 영역에서 벗어나면 안되나 봅니다..ㅎㅎ 왜냐구요? 클로져도 문제가
좀 심각하거든요... 이름하여 "Memory leak(메모리 누수)" 현상 때문입니다.

메모리 누수의 전체적 그림은 중급강좌정도에 보실 수 있겠네요. 여기서는 클로져에 의한 메모리 누수에
대해서만 다루겠습니다. 메모리 누수 모델이 몇가지 있는데 그걸 다 다루자면 제목에서 보듯이 [기초강좌]에서 범위가 벗어납니다. 우리가 좀전에 뭘 배웠습니까? 영역을 벗어나면 문제가 된다고 했지요 ㅎㅎㅎㅎ

자 다시 본론으로 가서, 클로져는 한 내부함수의 지역변수를 함수 리터럴을 통하여 밖으로 꺼내오는 것을
의미한다 했습니다. 그럼 제가 질문을 해보겠습니다. 그 한 내부함수가 종료되면 클로져에 의해 밖으로
튀어나온 변수는 어떻게 될까요? 그렇습니다... 계속 살아 있습니다. 계속 살아있으므로 부모함수가 죽었는데도 불구하고 계속 호출되어 사용됩니다. 나중에 다시 이야기 되겠지만 이것이 "IE에서의 메모리 누수 모델 1"
입니다. 보통 FireFox나 오페라 같은 브라우저는 클로져가 생성되어도 참조값이 0이면 브라우저메모리에서
GC에의해 소멸되게 됩니다. 허나, IE는 그렇지 못하여 문제가 되는거죠. 전 강좌를 열심히 보신분이라면 쉽게 이해하시리라 봅니다. 클로저의 메모리 누수는 이쯤으로 마치겠습니다. 사실 메모리 누수에 대해서는 할말이
무지 많습니다. 허나, 역시 범위를 넘기면 문제가 ㅎㅎㅎㅎ

이번강좌는 이쯤으로 해서 마무리 하겠습니다. 좋은 하루 되세요

posted by blankus

Javascript_base  |  2007/06/01 11:51
앞장의 글을 쓰고보니 시간이 남는군요... 언제 포스트가 될지 모르겠지만.. 시간날때 미리미리 써둡니다..ㅎㅎ
앞장에서 미리 예고해드렸듯이 이번 강좌는 굉장히 중요한 부분이라고 할 수 있습니다. 과거 Javascript를
그냥 폼의 형식이나 체크하고, 값을 체크할때나 써먹던 상황에서는 몸소 느끼지 못했지만 Ajax붐이 불면서
클라이언트의 개발또한 서버쪽 개발 못지않게 복잡도를 자랑하게 되었습니다. PrototypeJS니 DoJo니,
Yahoo UI ToolKit 등 많은 Javascript 라이브러리들이 등장하고 발전하고 있습니다.
이런것들의 등장으로 과거 소외받던 Javascript가 이제서야 비로소 프로그램의 언어로서
인정받기 시작했다고 해야할까?
그런 느낌입니다. --; 또 이상한 이야기를 하고 있었네요. 각설하고 본론으로 들어가겠습니다.

앞절에서 이미 언급한 부분입니다. Scope에 관한거죠. 못읽어 보신분이라면 언능가서 먼저 읽으시길 바랍니다. 이 강좌를 하면서 Scope의 개념이 없이는 절대 안되는 부분이거든요. 물론 깊게 설명하지는 않았습니다만,
이번 강좌를 이해하는데 많은 도움이 되리라 생각합니다.

//중첩함수
function A(){
var a = "1";
  function B(){
    var b = "2";
  }
}


이러한 함수가 정의되어 있다고 가정합시다. 함수 A는 a라는 지역변수를 가지고 있고 함수 B는 함수 A안에서
존재하고 b라는 지역변수도 가지고 있습니다.
깜짝 질문, 함수 B에서 a라는 변수를 참조할 수 있을까요? 없을까요? 앞장에서 했던 강좌를 유심히 보신분
이라면 쉽게 알 수 있을 겁니다. 답은 "참조할 수 있다" 입니다. 답은 앞장의 강좌를 다시 읽어서 확인하시기 바랍니다.

참고로 위의 구문은 "중첩함수"라고 부르며 Javascript에서의 private을 만들때 사용하는 방법중에 하나입니다. 실제로 해보시면 아시겠지만, 함수 B는 함수 A안에서밖에 호출할 수 없으며 밖에서 함수 A를 가지고 함수 B를 참조하려 해도 안되는걸 아실 수 있습니다. A.B() <- 이런식으로 절대 호출 할 수 없습니다.

그럼 다음 함수를 보시죠.

<html>
<script>
 function OutFunc(){
   var out = "i'm a out"
   function InFunc(){
     var inner = "i'm a in "+"-----"+ out;
     return inner;
   }
   return InFunc;
 }

 var test_1 = OutFunc();
 var test_2 = test_1();
 alert(test_2);
</script>
<body></body>
</html>

이 스크립트의 결과가 어찌 될거라고 예상이 됩니까? 사실 이 함수 자체를 이해 못하시는 분도 있으리라
생각합니다. 절대 무시하는게 아닙니다. 다만 우리는 알게모르게 쉬운 스크립트만을 접하고 이렇게 구조적으로 파헤친적이 없기때문에 어려울 수 밖에 없었던겁니다. 처음부터 Java 나 C#처럼 배웠다면 이렇게 Javascript가 우리를 힘들게 하지 않았을거라고 전 생각합니다. 일단 실행부터 시켜보세요. 어떻습니까? 여러분이 예상했던 답하고 일치합니까? 일치하다면 자신있게 설명을 하실 수 있습니까? 없다면 아래를 봐주세요 ^^ㅋ

먼저 정리부터 해보죠.
1. Javascript에서의 단위는 함수이다.
2. 함수의 지역변수는 함수밖에서는 절대 호출 할 수 없고, 함수내부에서는 전역변수보다 지역변수가 우선한다.
3. 변수는 각각의 Scope를 가지며 자신의 Scope를 벗어날 수 없다.


이제 소스를 해석해보겠습니다. 다들 청심환 하나씩 드세요. ^^
OutFunc는 자신의 지역변수 out을 가지고 있고 중첩함수인 InFunc를 가지고 있습니다. InFunc는 자신의
지역변수인 inner를 가지고 있고 중첩된 함수(nested function이라고 표현합니다) InFunc는 지역변수 inner를 리턴하는군요. OutFunc는 중첩함수인 InFunc를 리턴하구요. 여기까지 이해하셨죠?

그리고 OutFunc를 실행하고 test_1에 담습니다..여기엔 뭐가 담길까요? 그렇습니다. 함수 InFunc가 담깁니다. 그리고 test_2에는 test_1에 담긴 함수를 실행하고 그결과를 담습니다.

그럼 답을 발표하겠습니다. 답은 "i'm a in -------- i'm a out" 입니다.

제가 묻겠습니다. 변수 inner는 어디에 속해이어야 하는 거죠? 네. 함수 InFunc에 속해서 그 Scope안에서만
존재 해야하며 그함수가 종료되었을때, 같이 사라져야할 변수입니다. 그런데 지금의 모습은 어떻습니까?
alert()을 통해서 inner의 값을 찍고 있습니다. 도대체 어떻게 된 것일까요? 위에 정리한 1,2,3은 도대체
어쩌라고 이렇게 결과가 나오는 겁니까?

눈치가 빠르신분은 이미 알고 계셨을 겁니다. 그렇습니다. 이것이 바로 "클로져(Closure)" 입니다.
클로져의 정의는 "다른 함수내에서 내부객체로 생성된 함수 리터럴을 반환하여 호출 프로그램에서 이를 변수로 배정한 것" 이라고 정의하고 있으며 부연설명으로는 "함수가 동작하는데 필요한 데이터 영역 확장"이라고 하고 있습니다.[o'relly - Javascript for web 2.0 5장]

제가 더 덧붙여 설명하면 첫번째  OutFunc()를 실행함으로써 InFunc()함수를 OutFunc()의 안에서 바깥쪽으로
끄집어내어 영역을 변경(확장)하고 두번째 test_1()을 다시 한번 실행함으로써 inner의 값을 직접 호출 할 수 있도록 호출 프로그램으로 영역을 변경(확장)한 것입니다. 이로써 inner라는 변수는 더이상 OutFunc의
InFunc안에 갇혀있지 않고 어디서든지 호출 될 수 있는 전역변수화가 되어버린 것이죠.
여기까지 이해하셨다면 당신은 이미 중급의 문턱까지 온것입니다.
사실 클로져란것을 정확하게 알고 있는 사람은 드물뿐 아니라 "의도하지 않은 클로져의 생성"으로 고통받고
있는 개발자들도 많습니다. 그만큼 어렵고 이해하기 힘든 개념인 것입니다.

결과적으로만 보면 상당히 훌륭해보이고 멋져 보이지만, 사실 내면엔 "메모리 누수"라는 문제점을 안고
있습니다. 메모리 누수에 대해서는 다음 강좌인 "함수-3"에서 자세히 다뤄보도록 합시다.
오늘은 이만 접어야 겠네요..ㅋ 퇴근시간이 가까워 져서리..ㅋㅋ
그럼 다음 강좌까지 다들 건강조심세요.. 더위가 심하네요..

posted by blankus
Javascript_base  |  2007/05/31 17:46
오늘은 공짜로 영화를 보게되서 기분이 좋은~ 날입니다. ㅎㅎ 회사 동료가 이벤트에 당첨되어 같이 영화를 보게된거죠~ ^^* 여러분들도
가끔은 문화생활을 해주세요~ 생활의 활력소까지는 아닙니다만, 지루한 일상에서 벗어날 순 있어요..ㅎㅎ

오늘의 주제는 함수입니다. 함수란 뭘까요? 함수란, 뭔가를 넣으면 뭔가를 내뱉는 놈입니다. 쉽죠? 이개념만 잡히면 암것도 아닌거죠.
혹시 여러분들은 멧돌을 보신적이 있으신가요? 멧돌에 콩을 넣으면 콩이 갈려져서 나오지요. 그렇습니다.
함수를 설명하고 있는겁니다. "함수는 인자를 받아서 처리하고 그 결과를 리턴한다"가 정확한 문구이고 그것을 저는 멧돌에 비유하고 있습니다.
인자는 콩이고, 결과는 갈린콩(사실, 이용어때문에 회사직원들에게 물어봤으나 정확한 용어를 모름,
알면 알려주세요^^) 입니다.

쉽게 이해하셨으리라 생각됩니다. 계속해보죠. 이러한 함수는 Javascript에서 만들어 낼 수 있는방식이 참으로 다양합니다. 그중에서도 우리는 정적함수 / 익명함수 / 리터럴 함수 를  다뤄보겠습니다.

- 정적함수(선언적 함수)
function 함수명 (인자1, 인자2, ...., 인자n) { ...처리식... }
많이 보던 형식입니다. 말그대로 정적함수이며 한번 파싱되면 메모리에 상주되어 몇번을 어떻게 호출하던지
동일한 함수객체가 생성됩니다.

- 익명함수
var fnc = new Function("인자",....,"...처리식...")
익명, 말그래로 이름이 없습니다. 직접적으로 함수를 명명하거나 선언하지 않는 함수를 익명함수라고 합니다. 익명함수가 정적함수(선언적 함수)와 다른 차이점은 익명함수는 매번 호출될때마다 다른 함수객체가
생성됩니다. 즉 런타임때 동적으로 생성되어 실행되어 지는것이죠.

- 리터럴 함수
var fnc = function (인자){..처리식..}
생긴 모습은 익명함수와 비슷하게 생겼지만 특성은 정적함수(선언적 함수)와 동일합니다. 즉 익명함수와는
다르게 페이지 로딩시 한번만 파싱되고 메모리에 상주하며 생성된후 몇번을 호출해도 같은 함수객체를
사용합니다. 여기서 오해가 있으실 것같아 부연설명합니다. 아래와 같은 함수가 있다고 가정합니다.

function test(){
   this.fnc = function(){ alert('call func'); }
}

var a = new test();
var b = new test();

위에서 말한 "몇번을 호출해도 같은 함수객체를 사용"이란 표현은 "a.fnc()을 어디에서 몇번을 호출하던지"와 동일한 뜻입니다.

b와같이 새로 객체를 생성한 것에 대해서는 적용되지 않습니다. 그리고 각각의 새로생긴 인스턴스는 동일한
객체가 아닙니다. 물론 같게 생성할 수도 있습니다. 같게 생성하려면 중고급 강좌에서 보실 수 있을 Design Pattern의 싱글톤 패턴을 공부하시면 적용하실 수 있습니다. 우리는 급할게 없습니다. 디자인 패턴에 대해서는 나중에 다룰 것이니 이번강좌에선 그냥 넘어가시지요~

이상으로 함수에 대해서 알아봤습니다. 다 알고 계신거죠? 하지만 바로 다음에 나올 강좌는 "함수 2" 입니다.
여기서는 함수의 scope와 클로져, 메모리 누수에 대해서 다루겠습니다.
오늘은 시간이 별루 없는관계로 슬쩍 끄적였습니다 ^^

posted by blankus
Javascript_base  |  2007/05/31 13:19

오늘도 무쟈게 덥군요 ^^; 좀전에 회사 사람들하고 잠시 밖에나가 잡담을 하며 바람좀 쐬고왔습니다.
역시 사무실에 일할때보단 밖에서 놀때가 더 좋군여..ㅎ

오늘은 By value와 By reference에 대해서 알아보겠습니다. 날도 덥고하니 조금은 짧게 이야기해봅시다.
사실 이부분은 제가 C를 공부할때 알게되었습니다만, Javascript에서는 크게 신경안쓰고 작업했던 부분입니다. C를 공부하신 분은 아시겠지만, C에는 포인터란 개념이 있습니다. 물론 Javascript에서는 없습니다.
하지만 표면적으로 C처럼 포인터를 핸들링 하지 않는것 뿐이지, 개념은 필요한 부분입니다.

포인터.. 그놈은 이런놈입니다. 보통 우리가 변수를 선언하고 무언가를 그 변수에 담을때, 그때 그 무언가는
메모리에 저장되게 됩니다. 메모리에 저장될때, "나는 메모리의 어디에 위치해있다."라고 알려주는데 그게 바로 "포인터" 입니다. 말그대로 무언가를 가리키는거죠. 그래서 C에선 일반변수와 포인터 변수를 구분해서
사용하는데, Javascript에서 사용하는 변수는 C에서의 일반 변수가 되겠습니다. 포인터 변수는 뭔가 저장된놈의
메모리 주소를 가지고 있는거구요. 일반 변수는 by value가 되고, 포인터 변수는 넓은 의미에서 by reference가 됩니다. 물론 Javascript에 100% 적용되는 설명은 아닙니다.
여기까지는 쉽게 이해가 가실거라 생각됩니다. 아직 부족하다구요? 그럼 더 쉽게 --;

by value의 참조는 변수에 값을 직접할당하는 방식이며 (변수를 박스라고 생각하시면) 박스안에 내용물이
중요한 놈이죠.
by reference의 참조는 변수에 값을 직접 할당하지 않고,(변수를 박스라고 생각하시면) 박스의 위치에
관심이 있는 놈입니다.
내용물에 뭐가 담겨져있고, 그 내용물이 어찌되던간에 그 박스의 위치만 잘 가지고 있으면 되는 놈이죠.
나중에 변수를 call하면 by reference의 참조는 "값을 가져오라고? 그래. 난 박스주소를 알고있으니까, 그박스에 뭐가있는지는 잘모르지만 내용물을 넘겨줄께"라고 행동하게 됩니다.

그럼 Javascript에서는 위의 개념을 어떻게 가지고 있을까요? 이제 소스를 보면서 이야기해보죠.

<html>
<script>
   //첫번째 구문
   var ref_1 = "string...";
   var test_1 = ref_1;
   ref_1 = "none";

   //두번째 구문
   var ref_2 = new String("hello world");
   var test_2 = ref_2;
   ref_2 = new String("world");

   //세번째 구문
   var ref_3 = new Array("one", "two", "three");
   var test_3 = ref_3;
   ref_3[0] = "1";

</script>
<body>
</body>
</html>


우선 '첫번째 구문'에 대해서 살펴보죠. 아주 쉽습니다. 단순히 문자열을 변수에 담고있고, 그것을 다시 다른 변수에 담았습니다.
그리고 원래 변수의 값을 변경했군요.

'두번째 구문'은 결과적으로 '첫번째 구문'과 동일하지만 다른점이 하나 있습니다. 바로 new String이란 것을 사용해서 변수에 담고있습니다.
'첫번째 구문'에서 ref_1의 타입은 Stirng이지만, '두번째 구문'에서 ref_2의 타입은 Object입니다. 역시 마지막에선 다른 String Object로
값을 변경하고 있네요.

'세번째 구문'은 많이 사용하는 배열입니다. 배열은 자체가 Object인건 아시죠? 역시 이것도 test_3이라는 변수를 만들고 ref_3을 담았습니다.

이상 소스설명은 드렸습니다. 여기까지 이해가 가시나요? 혹시 안가신다면 제게 질문을 하시거나, 구글링을통해 학습이 필요합니다.
이제 제가 질문을 드리겠습니다.

1. alert(test_1)를 실행하면 값이 어떻게 나올까요?
2. alert(test_2)를 실행하면 값이 어떻게 나올까요?
3. alert(test_3)를 실행하면 값이 어떻게 나올까요?

3개의 답을 모두 자신있게 말씀하셨다면, 거기에 답까지 맞으셨다면 축하합니다 ^^*

1번의 답은 "String..."이 출력됩니다. 이유는 String타입의 값들은 by value에 의해서 참조가 됩니다.
다시말해서, test_1은 ref_1의 주소값을 가지고 있는게 아니라 "String..." 자체의 값 즉, value를 가지고 있는겁니다. 그러므로 아무리 ref_1의 값을 변경해도 값에의한 참조(by value)를 한 test_1은 영향을 받지
않는거죠.

2번의 답은 3번을 설명하고 다시 이야기하겠습니다.
3번의 답은 "1, two, three"가 되겠습니다. 왜일까요? 그렇습니다. 둘중에 하나니까 그렇습니다 --;
위에서 값에의한 참조였으니, 이번엔 그반대의 경우겠지요 ^^; 물론 맞는 답입니다만, 정확한 설명을 드리면, ref_3은 Object를 담고있습니다. 그리고 test_3는 ref_3을 참조하지요. 그리고 Object는 by reference에 의해서 참조가 됩니다. 위에서 제가 말씀드린게 by reference가 되면 값을 가지고 있는게 아니라 참조되는 놈의 주소를 가진다고 말씀드렸습니다. 이해가 되시는지요?
만약 값에 의한 참조가 되었다면 test_3는 값이 변경되기전의 ref_3을 참조했기때문에 test_3는 ref_3의 값의 변동에 상관없이 동일한 값을 가지고 있어야함에도 불구하고, 결과는 변경된 값을 가지고 있습니다. 바로 by value가 아닌 by reference에 의해 참조가 되기 때문이지요. by reference로 참조된 변수는 그안에 값이 어떻게 바뀌든지 상관없이 주소값만을 가지고 있으므로 나중에 주소안에 들어있는 값만을 내뱉어 줍니다.
위에 설명 드렸던 부분입니다.

그럼 2번은 결과가 어떻게 될까요? 참으로 애매한 부분입니다. 답은 "hello world"가 출력됩니다
new String으로 생성했으므로 분명 Object입니다, 그럼 by reference에 의해서 참조가 일어나야 정상이지만
결과적으로 그렇지 못합니다 --;
왜그럴까요? 여기에도 무언가가 있기 때문입니다.

바로 Wrapper Object가 범인입니다. Wrapper를 잘모르시는 분을 위해서 잠깐 설명을 드리겠습니다.
Wrapper는 보통 타입을 변경하기위해 사용합니다. String으로 사용하지만 나중의 변환을 위해 new String으로 생성하여 Object로 만들어 내는것입니다. 물론 Javascript에서는 자동 형변환에 의해 크게 사용되지는
않습니다.
다시 본론으로 돌아가서, Wrapper Object는 Object이지만서도 by value에 의해 작동됩니다.
[O'reilly의 Javascript The Definitive Guide 5/E 3장 참고]
(Javascript에서의 Wrapper Object는 String, Number, Boolen이 있습니다. )
그러므로 예상대로 "world"가 출력되지 않고 "hello world"가 출력되는 것입니다.

오늘은 조금 짧게 써보려고 했는데, 말이 길어졌군요 ㅎㅎ 오늘의 주제는 "참조"였는데 만족할 만한
주제였는지 모르겠습니다.
기초강좌라서 약간은 부담이 되는게 사실입니다 ^^; 최대한  쉽게 풀어서 설명하고 싶은데 생각처럼 그렇게
쉽지만은 않군요ㅋ 포스팅을 하다보니 벌써 저녁먹을 시간이네요.. 오늘도 야근모드인
개발자의 비애ㅋ

자 기초강좌가 언제까지 연재 될지 모르겠지만 가끔은 중급강좌도 쓰도록 하겠습니다.
즐거운 저녁식사 되세요~~

posted by blankus

태그 - javascript
Javascript_base  |  2007/05/30 18:09

5월의 막바지 입니다. 아~! 쿨럭.. 많은 분들이 왜 반말이냐고 그러하셔서...
존칭을 쓰기로 했습니다 ㅠㅠ
5월임에도 불구하고 많이 더운데... 오늘은 비온다고 우산도 준비해놨건만... 비는 안오고
덥기만 하군요. 사실 밖은 바람이 불어 시원한데... 사무실안은 덥습니다..
왜? 에어컨이 제자리쪽엔 안오걸랑요 ㅠㅠ
각설하고, 오늘의 주제에 대해서 이야기를 꾸려가보겠습니다.

오늘의 주제는 제목처럼 변수 scope입니다.. 주제는 변수의 스코프 이지만 전체적인 스코프에
대해서도 살짝 언급하겠습니다.
아시는 분들도 있겠지만, Javascript에서의 단위는 function입니다. 즉 function단위가 하나의 완벽한
구문입니다.
function단위로 실행이 되며, 메모리가 관리됩니다. 물론 위 규칙을 무시하는 구문도 존재합니다. 전문용어로 Closure라고 부르죠.
이 클로져에 대해서는 중급과정에서 심도 있게 다뤄보겠으니, 궁금하시더라도 참으시고 너무
궁금하시다  싶으면, 구글신의 도움을 받으시면 되겠습니다.

다시 본론으로 돌아와서, Javascript의 단위는 function이며 그 function안에서 메모리가 관리된다고
말씀드렸습니다.
function이 정의되고 실행되고, 더이상 참조가 되지 않으면 GC(Gabage Collector)에 의해 메모리에서
제거가 됩니다.
허나 모든것이 그렇게 되는건 아닙니다. 이름하여 "전역변수". 이놈은 특이하게도 function에
얽매이지 않고 page에 종속되어 있습니다. 전역변수가 선언되면 그 페이지가 갱신/소멸되기전까지는
메모리에 계속 상주하고 있는것이지요.

전역변수는 <script></script>안에서 function밖에 정의되어 있고 보통 아래와 같이 사용합니다
<script>
  var global = "i'm a  global vars";
</script>

또는 아래와 같이도 사용합니다.
<script>
  global = "i'm a  global vars";
</script>


두개가 무슨 차이냐구요? var로 선언을 한것과 안한것의 차이지요. 백문이 불여일견~! 다음 코드를 보시죠
<html>
<script>
  msg = "I'm  in the page";

  function fncScope(){
   var msg = "test";
   alert(msg);
  }
</script>
<body>
<script> fncScope(); </script>
</body>
</html>

자, 위의 스크립트를 실행하면 어떤결과가 나올까요? 답은 test가 맞습니다. 이유는 scope에 있습니다.
alert함수가 어디에 속해있나요? 그렇습니다. fncScope에 속해있습니다. 그렇기 때문에 자기의 소속인 fncScope의 msg변수를 우선시 합니다. 눈치가 빠르신 분들은 이미 알고 계셨을거라 생각합니다.
function 내부에서는 전역변수보다 지역변수가 우선합니다.

그럼 아래의 코드는  어떤 결과를 가져올까요?
<html>
<script>
  msg = "I'm  in the page";

  function fncScope(){
   alert(msg);
  }
</script>
<body>
<script> fncScope(); </script>
</body>
</html>


그렇습니다. 위 내용과 일치하는 부분입니다. 비록  alert가 fncScope에 속해있지만 지역변수가 없기때문에 전역변수인 msg를 참조합니다. 답은 "I'm  in the page"가 출력되죠 ^^
의외로 이번강좌는 좀 쉽게 느껴지는군요. ㅎㅎ 저만그런가요?

그럼 제가 문제 하나 내보겠습니다.
<html>
<script>
  function fncScope(){
    msg = "test";
  }

  function call(){
    alert(msg);
  }
</script>
<body>
<script>
   fncScope();
   call();
</script>
</body>
</html>


이 스크립트를 실행하면 어떤결과가 나올까요? 이 코드는 직접 실행해 볼 필요가 있습니다.
우선 집고 넘어갈것은
 1. Javascript에서의 단위는 function이다.
 2. function이 더이상 참조가 발생하지 않으면(참조값이 0이면) GC에 의해 메모리에서 제거된다

자... 자신있게 대답할 수 있나요? 답은 "test"가 출력이 됩니다.
제가 질문을 던지죠.
 Q : msg는 분명 fncScope에 속해있는 변수인데 어떻게 다른 함수인 call에서 호출 할 수 있는것일까요?
스스로 답을 하실 수 있다면, 이강좌는 더이상 무의미해집니다 ^^ 하지만 혹시 하나라도 더 건질게 있을 수
있으니 조금만 참고 글을 읽어 내려가 봅시다.

우선 msg가 선언된 모습을 보면, var로 선언되지 않았습니다. 저~ 위에 제가 언급한 내용에 의하면 <script></script>사이에 var로 선언되거나 var 없이 선언되는 것은 "전역변수"라고 말씀드렸습니다.
이는 var없이 선언한 모든변수는 function안에 있거나 밖에있거나 전혀 구애받지 않습니다.

즉, msg를 포함한 fncScope가 실행됨에 따라 전역변수 msg가 생성되었고, 전역변수이므로 다른 함수인
call함수에서 msg를 출력할 수 있었던 것이지요. 이해하셨나요?
다시한번 말씀드리면 var를 사용하지 않고 선언한 변수는 무조건 전역변수가 됩니다. 어떤분들은 전역변수가 Javascript에서 별쓸모가 없다고 하시는 분들도 계십니다. 허나 이는 잘못된 생각입니다.
카운터라든지, 기타 다른작업에 꼭필요한 존재입니다.

그리고 전역변수이든 아니든 우리는 무조건 var를 사용하여 변수를 생성해서 써야하고, 반드시 전역변수와
지역변수를 구분하여 사용할줄 알아야 하겠습니다.

쉽지만 결코, 무시해서도 쉽게 지나쳐서도 안되는 부분입니다. Javascript에서 scope를 무시한다는건 Javascript를 제대로 배우고싶지 않다는 의미기도 하니까요.
절대 그냥 쉽게 생각치는 마세요.

이 scope 가 나중에 클로져의 개념에 많이 도입이되고 메모리 누수에 관련도 있는 부분입니다.
이러한 부분은 중급이상의 강좌에서 보실 수 있습니다. (인제 기초강좌인데 언제 중급까지 --;)
하루에 두개의 강좌를 썼더니 힘이 좀 드는군요..ㅎㅎ
오늘이 첨이라 긴장도 되고..ㅋㅋ 암튼 열심히 써보겠습니다. 누구를 위해서도 아니고 저 자신을 위해서
그럼 좋은밤 되세요 *^^*

posted by blankus

Javascript_base  |  2007/05/29 20:54

시간이 어떻게 될지 모르겠지만 앞으로 계속 쭉~~~~ 강좌(?)를 쓸예정이다.
참고로 혼자 떠드는 스타일이라 존칭어는 과감하게 생략토록 하겠다.ㅋㅋ
강좌라고 하기엔 좀 납득하기 어려운 부분도 있겠지만 글머리를 봐주길 바란다.
그렇다! 기초강좌다 -_-;

기초강좌의 주된 목적은 초보 또는 아직 Javascript에 대한 개념이 정립되지 않은 상태에서
이것저것 하다보니 헛깔리는 분들을 위한것이 주가 되겠다.

오늘은 첫날이므로 조금은 쉽지만 자주 헛깔릴 수 있는 것을 다뤄보겠다.
이름하여 Javascript의 Runtime이다.

말그대로 "Runtime"... (실행시간이 아니다 --;) 실행할때의 시점으로 봐주길 바란다.
주절주절 떠드는 것보다 아래의 코드를 보며 접해보는게 좋겠다 ^^*

<html>
  <script>
   function test_1(){ alert("test_1"); }
   function test_2(){ alert("test_2"); }
   function test_3(){ alert("test_3"); }

   test_1();
  </script>
  <body onload="test_2()">
   <script>test_3()</script>
  </body>
</html>

위 소스는 그리 어렵지 않다. 아니다 하나도 안어렵다. 만약 이것이 어렵다고
느끼시는 분이 있다면.... 대.략.난.감. !!

자, 해설을 해보자. 여러분들은 위의 실행순서가 어떻게 될지 예상이 되는가?
여기서 두그룹으로 나눠볼 수 있겠다.
1번째 그룹은 아마 test_1 -> test_2 -> test_3 으로 예상할 것이고,
2번째 그룹은 아마 test_1 -> test_3 -> test_2 으로 예상할 것이다.
혹시, 이 두그룹에 속하지 않는 당신이라면... 역시... 대.략.난.감 !!

직접 실행해보면 알겠지만 답은 2번째 그룹이 정답이다. 왜 이런 일이 발생할까?
쉽게 생각하면 1번째 그룹이 답이 될 수도 있다. 왜? 음.. 이제부터 그룹1을 대표해서
설명을 해주겠다 (물론 틀린해석이지만 ^^.. 가능성을 이야기해주고 싶은것이다)

test_1은 당연 먼저실행된다. 왜냐면 Javascript는 인터프리터 언어이기때문에
위에서 아래로 순차적으로 해석되어지면서 실행이 된다. 그래서 test_1이 가장먼저
실행이된다. 그리고 자주보던 onLoad 문이다..그렇다 우리는 잘배웠다!! onLoad는
body가 전부 로드되면(여기에 함정이 있다) 실행되는 것이다. 그래서 test_2가 실행되고,
body 안에 있는 test_3가 실행된다고 생각된 것이다. (사실 나도 첨엔 그리 생각했다^^;)

하지만 위에도 말했듯이 위에 말은 사실이 아니다. 더 정확하게 말하면 오해이다.
자! 그럼 사실대로 오해없이 이해해보자.

위의 잘못된 설명중 초반엔 맞는 설명이다. 어디까지냐면, onLoad전까지 이다. 그다음엔
body의 onLoad를 자세히 이해할 필요가 있다. body는 무엇인가? 그렇다. 단순한 몸뚱이가 아니다 ^^
body는 html의 몸뚱이이며 DOM객체의 일부이다. onLoad는 body, 더 정확하게는 DOM의 일부인
body가 전부 로드되었을때 실행이 되는 것이다. 그런데 왜 test_3가 먼저실행되었냐?
그건 위에 설명된 인터프리터 언어의 특성때문에 위에서 순차적으로 읽어내려가면서 실행이
되기 때문이다. 쉽게 DOM은 DOM이고 JS는 JS인것이다. 아주~ 나중에~ 다시 언급되겠지만
DOM의 참조를 JS에 넘기면 IE에서 memory leak이 발생한다. 잠시 어려운 이야기를 했는데
나중되면 다 이해하리라... 다시 본론으로 쿨럭! -_-;
body안에 스크립트가 있긴하지만 DOM의 일부가 아니기에 인터프리터의 특성으로 먼저실행되어지고,
그다음에 body onLoad가 실행되어지는 것이다. 이해하셨는가? 힘들게 설명했는데, 이해못하면 안된다 ㅠㅠ OTL

자 여기까지 이해했다면, 난이도를 조금 높여보자.

<html>
<script>

test_2();

function test_5(){
 this.msg = "hello~ test_5";
 this.call = function(){
  alert(this.msg);
 }
 test_4();
 this.call();
}

function test_1(){ alert("test_1"); }
function test_2(){ alert("test_2"); }
function test_3(){ alert("test_3"); }
function test_4(){ alert("test_4"); }

</script>

<body onload="test_1()">
<script>
 new test_5();
 test_3();
</script>
</body>
</html>

문제는 동일하다. 실행순서 실행결과를 맞추면 된다. 어려워 보이는가? 절대 그렇지 않다.
결론부터 말하자면 test_2 -> test_4 -> test_5 -> test_3 -> test_1 순이다.
이해가는 사람도 있을것이고, 아직 잘 이해가 안되는 사람도 있을 것이다. 어쩔수 없다.
이해가 안되면 되게해야 인지상종의 정신이 아니던가??

해설 들어간다.

Javascript는 인터프리터이며, 순차적으로 실행한다 했다. 근데!!!! 이게 왠말인가?
함수를 정의하기도 전에 호출을 해버린게 아닌가? 이게 말이되는건가? 결론적으로 말이된다.

Javascript는 인터프리터이므로 순차적이다. 그러나 순차적이 한줄한줄 순처적이기도 하지만, <script></script> 안에서는 한줄한줄이나, <script></script>로 봤을땐 한통속인것이다.
즉, test_2()를 먼저 호출했지만 Javascript엔진이 <script></script>한 구문을 해석하는 시간이
test_2()를 호출하는 시간하고 크게 차이 안났다는 이야기다. 아니 더 정확하게 말하자면 거의 동시에
이루어졌다고 봐야한다.
더 적나라하게 말하면 <script></script>사이에 어디에서라도 수가 정의되기전에 함수를 호출해도 동일한
태그안에서 함수가 정의만 되어있으면 호출이 된다는 이야기이다.(안될 경우있음)

어떤가? 말도 안되는 일이지 않는가? 아무리 빠르다고 해도 이게 말이되는건가? 그렇다
Javascript는 원래 말이 안되는 언어이다.. 완벽한 oop도 아니면서 oop에 가깝다.
코딩의 자율성도 상당히 높아서 잘못된(Java또는 그외 언어와 비교하여) 코딩도 맘넓게 이해해주는
센스도 있다.

여기서 잠깐! 위에 보면 test_5()를 보시라.. 좀 특이하게 생겨먹었다.
Javascript에서 "like class"(oop에서의 class와 비교하여)를 생성하는 방법중에 하나이다.
자세한건 뒤에 다루기로 한다. 여기서는 그냥 이런것도 있구나, 이렇게 쓸수 있구나하는 정도까지만
이해해 두자.

근데, 아무리 성격이 좋은 Javascript라도 안되는게 있다.

<html>
<script> test_2(); </script>
<body>
</body>
<script>
 function test_2(){ alert("test_2"); }
</script>
</html>


위 스크립트를 실행하면 어떤 결과가 나올지 예상이 되는가? 그렇다.. 에러다 -_-;;

왜 그러한가? 설명은 위에 있다. Javascript에서 엔진이 해석하는 순서는 <script></script> 단위이고,
그안에서는 대부분 자유롭게 기술할 수 있다.(안되는 경우가 있다. 언제냐고? 스스로 생각해보자 ^^)
허나 위의 구문은 하나의 <script></script>에서는 정의되지 않은 함수를 호출하고,
아래의 다른 <script></script>에서는 함수를 정의했다. 그래서 안되는거다.
Javascript의 엔진이 해석하는 단위에서 정의와 호출이 따로 있기 때문이다.

이상 Javascript 에서의 런타임에 대해서 간략하게나마 정리해 보았다.
간혹 이해가 안가시는 분이나, 도통 모르겠다고 생각되시는 분들은 차근차근 다시 위 글을 읽어 보시기
바란다. 위 내용은 어느 책에도 나와있지 않기때문에 오로지 경험에 의해서만 알 수 있는 것이다.
쉽게 "노하우"란 이야기이다. 다들 열심히 공부하여 앞으로 나올 Javascript 2.0시대에
조금이라도 쉽게 다가갈 수 있도록 화이팅이다.

posted by blankus

Javascript_base  |  2007/05/29 18:10