공부내용 정리 :: JavaScript 기초 2
1. 스코프(Scope)
유효범위라고도 불리는 스코프(Scope)는 변수의 수명을 의미한다.
var scope = 'global';
function checkScope(){
alert(scope);
}
checkScope();
상기의 예제에서 함수 checkScope()를 호출한다면, 어떠한 값이 출력이 될까, 당연한 이야기지만 global이 출력될것이다. 이렇게 함수 밖에서 생성된 변수는 해당 애플리케이션 전역(Global)에서 접근이 가능하기 때문에 전역변수라고 한다.
var scope = 'global';
function checkScope(){
var scope = 'local';
alert('함수안 ' + scope);
}
checkScope();
// 'local'
alert('함수밖 ' + scope);
// 'global'
그렇다면 이번에는 함수 외부 (전역)에 scope를 선언하여 global이라는 값을 할당하고, checkScope 함수를 선언하며 내부에 다시한번 같은 이름의 변수인 scope를 생성한 뒤 local을 할당한 다음, 함수를 호출하고, scope를 console에 출력한다면 어떤 일이 일어날까? 상기 코드와 같다.
전역변수 scope에는 global이 할당되어 있는 상태이다. 그 후 함수 checkScope가 선언되면서 함수 내부적(지역적)으로 사용될 scope가 다시 생성된 것인데, 이 때 함수 내부적으로 선언된 변수는 함수의 코드블럭이 끝나는 시점에 효력을 잃는다.
따라서, 함수 내부에서 다시 선언된 scope에는 local이 할당되게 되고 함수 내부에서 scope가 사용되었다면, 내부적으로 새로 생성된 변수에 저장된 값을 찾아서 사용하게 되는 것이다.
그렇기 때문에 함수를 호출하면 내부적으로 할당된 local이 호출되고, 호출하지 않고 그대로 scope의 값을 출력하면 global이 출력되는것이다.
하기의 내용은 자바스크립트에서 사용되는 스코프를 이용한 모듈화의 기본적인 내용이다.
MYAPP = {}
MYAPP.calculator = {
'left' : null,
'right' : null
}
// MYAPP = {
// calculator : { "left" : null, "right" : null }
// }
MYAPP.coordinate = {
'left' : null,
'right' : null
}
// MYAPP = {
// calculator : { "left" : null, "right" : null } ,
// coordinate : { "left" : null, "right" : null }
// }
MYAPP.calculator.left = 10;
MYAPP.calculator.right = 20;
function sum(){
return MYAPP.calculator.left + MYAPP.calculator.right;
// 30
}
document.write(sum());
// 30
어플리케이션 전반적으로 선언된 MYAPP은 전역변수이다. 따라서 MYAPP 안에 값을 넣고 함수 안에 사용하여 리턴한다면 상기와 같은 값을 얻을 수 있다는 것은 쉽게 도출된다.
(
function(){
var MYAPP = {}
MYAPP.calculator = {
'left' : null,
'right' : null
}
MYAPP.coordinate = {
'left' : null,
'right' : null
}
MYAPP.calculator.left = 10;
MYAPP.calculator.right = 20;
function sum(){
return MYAPP.calculator.left + MYAPP.calculator.right;
}
document.write(sum());
}()
)
그러나 상기와 같이, 모든 로직을 함수로 묶은 다음에 그것을 다시한번 괄호로 묶는다면, 익명함수를 호출하게 됨으로서, MYAPP은 익명함수 안에서만 사용되어 사라져버리는 지역변수가 된다.
또한, 자바스크립트의 특징이 드러나는 스코프 예제가 있었는데, 다음과 같다.
일반적으로 블록이 있는 언어들 ( { } )은 블록에 대한 스코프를 제공하는데, 자바스크립트에서는 함수에 대한 스코프만 제공한다고 하였다. 다음과 같다.
가령 자바에서,
public static void main(String[] args) {
public void main() {
for ( int i ; i < 10 ; i++ ) {
String name = "Sam";
}
System.out.println(name);
}
}
상기와 같은 코드를 작성하였다 하면 신택스 에러가 나올 것이다. 그 이유는 name이라는 변수는 for문 코드블럭 안에서 생성된 지역변수인데, 그것을 for문 코드블럭 밖에서 호출하고 있기 때문이다.
그러나 자바스크립트에서 다음과 같다면,
for(var i = 0; i < 1; i++){
var name = 'sam';
}
alert(name);
// sam
오류없이 for문 블럭안에 있는 name변수가 호출되어 값을 출력할 수 있게된다. 코드레벨에서 보면 확실히 알 수 있듯이, 다른 언어와는 다르게 스코프가 함수에만 적용이 된다는 것을 알 수 있는 것이다.
var i = 5;
function a(){
var i = 10;
b();
}
function b(){
document.write(i);
}
a();
상기와 같은 코드가 있다고 가정한다면, a메소드가 호출되었을때 어떠한 값을 출력할지 예측해보자. 현재 전역변수 i에는 5가 할당되어있다.
그리고, a 메소드를 정의하면서 지역변수 i를 생성하여 10을 할당하고 b를 호출하였다. a메소드의 정의가 끝난 다음, b메소드를 정의하며 i를 출력하는 로직을 생성하고 정의가 끝이났다. 그 후 a메소드를 호출한 것인데, 이때 어떠한 값이 출력되는지를 예측하는 예제인 것이다.
이때 정답은, 5이다. 자바스크립트는 함수가 선언된 시점에서 유효범위를 갖는다. 이러한 유효범위를 정적유효범위(static scoping)혹은 렉시컬 스코핑(lexcial scoping) 이라고 한다.
2. 함수의 활용
본 장에서는 함수의 활용에 대하여 정리하였다.
2-1 값으로서의 함수
자바스크립트에서는 함수도 객체이다. 따라서 일정한 값이 될 수 있는것이다. 이것은 자바스크립트만의 특징이다. 타 언어와는 다르게 함수가 직접적으로 값이 될 수 있는 것이다. 다음과 같다.
function a(){}
// a = funnction() {}
이렇게 메소드 a는 변수 a 안에 함수가 담겨있는것과 같은 효과를 낸다고 생각할 수 있는 것이 자바스크립트에서, 값이 함수가될수 있다는 것이다. 상기와 같이, 함수가 바로 값이 되어 처리될 수 있기 때문에 다음과 같은 예제도 실행이 가능하다.
function cal(func, num){
return func(num)
}
function increase(num) {
return num+1
}
function decrease(num){
return num-1
}
alert(cal(increase, 1));
//2
alert(cal(decrease, 1));
//0
예제에서 알 수 있듯이, cal이라는 메소드의 인자로 메소드와, 변수 하나를 인자로 받고, 인자로 넣을 메소드를 두개 정의한다음에, cal을 호출할때 함수의 이름만 인자로 전달하고 값을 따로 전달해도 실행이 되는 것을 확인할 수 있다. 이렇게 자바스크립트에서는 함수를 그 값으로서 사용할 수 있는 것이다.
이렇게 된다면, 함수의 리턴값으로 함수를 사용할 수도 있다. 함수는 값으로 치환될 수 있기 때문에, 함수의 로직에서 리턴이 될 때 치환될 로직이 들어있는 함수를 사용하여 값으로서 리턴을 하면 되는 것이다. 같은 맥락으로 배열의 값으로도 사용할 수 있다.
// 리턴값으로서의 함수
function cal(mode){
var funcs = {
'plus' : function(left, right) {
return left + right
},
'minus' : function(left, right) {
return left - right
}
}
return funcs[mode];
}
alert(cal('plus')(2,1));
// 3
alert(cal('minus')(2,1));
// 1
// 배열 값으로서의 함수
var process = [
function(input) {
return input + 10;
},
function(input) {
return input * input;
},
function(input) {
return input / 2;
}
];
var input = 1;
for(var i = 0; i < process.length; i++){
input = process[i](input); // 함수가 차례대로 하나씩 실행됨
}
alert(input);
// 60.5
2-2 콜백
함수가 값으로 사용될 수 있는 특성을 이용한다면, 함수의 인자로 함수를 전달할 수 있게 된다. 2-1과 같다. 이때 값으로 전달된 함수는 호출될 수 있기 때문에, 이를 이용하면 함수의 동작을 바꿀 수 있다. sort를 예제로 들어보았다.
function sortNumber(a,b){
// WAY1
if ( a > b ) {
return 1
} else if ( a < b ) {
return -1
} else {
return 0
}
// WAY 2
return b-a;
}
var numbers = [20, 10, 9,8,7,6,5,4,3,2,1];
number.sort()
// [ 1, 10, 2, 20, 3, 4, 5, 6, 7, 8, 9 ]
alert(numbers.sort(sortNumber));
//[ 20, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1 ]
상기 콜백에 대한 내용은 Ajax의 중요한 개념으로서 활용된다.
2-3 비동기 처리, Ajax
자바스크립트의 콜백은 비동기처리에서 중요한 개념으로 사용되는데, 비동기 처리에 대해서는 따로 정리하도록 하고, 코드단에서만 확인하도록 하겠다.
// data.json.js
{
"title":"JavaScript",
"author":"egoing"
}
// demo1.html
<!DOCTYPE html>
<html>
<head>
<script src="JQUERY CDN"></script>
</head>
<body>
<script type="text/javascript">
$.get('./data.json.js', function(result){
console.log(result);
}, 'json');
</script>
</body>
</html>
Jquery에서 제공하는 $ 객체의 get메소드를 이용하여, 해당 디렉토리의 파일을 수신받아 result에 할당하여 출력하는 기본적인 예제이다.