[Javascript] 함수 스코프(Scope)

함수 스코프(Scope)

스코프의 사전적의미는 범위이며, 여기에서는 변수 또는 함수의 유효범위를 가리킨다.

지역변수와 전역변수의 개념과 차이

전역변수는 자바스크립트 어디에서든 사용할 수 있는 변수이고
지역변수는 함수 스코프에서만 사용할 수 있는 변수이다.

따라서 스코프 밖에서 myFunc()함수를 호출하면 함수 스코프에서 선언한 지역함수가 아닌 전역함수가 실행된다.

function myFunc(){  //전역함수
   alert("전역함수");
}

function outerFunc(){   
  function myFunc(){ //지역함수
   alert("지역함수");
  }
  myFunc();       //지역함수 호출
}

outerFunc();
myFunc();       //전역함수 호출

전역과 지역을 나누는 이유

프로젝트 규모가 커지면 여러명의 개발자가 투입되는데 만약 같은 이름의 전역변수나 전역함수를 사용하면 충돌이 발생한다. 또한 다른 개발자가 이미 개발해 놓은 라이브러리나 플러그인의 변수 또한 함수의 이름이 같은 경우에도 충돌이 발생할 수 있다.

같은 이름의 함수를 선언한다면 어떤 결과가 나올까?

다음과 같이 첫번째 전역함수가 호출되어 200이 결과로 나올 것으로 예상되지만 100이 출력된다.

<script>
    var num=100;

    function menu(){
        num += 100;
        alert(num);
    }
    menu();

    function menu(){
        alert(num);
    }
// 두번째 전역함수가 호출됨 
// 따라서 결과는 200이 아닌 100이 호출
</script>

즉시실행함수

위 예제처럼 같은 이름의 함수를 선언하지 말고 지역함수를 사용하여 함수를 선언했다면 함수가 충돌하는 불상사가 일어나지 않았을 것이다.

이런 충돌문제를 해결하기 위해서는, 즉시실행함수를 사용하면 된다.

아래 예제와 같이 즉시실행함수에 지역변수와 지역함수를 선언하면 충돌을 방지할 수 있다.

<script>
    (function () {
        var num = 100;

        function menu() {
            num += 100;
            alert(num);
        }
        menu();
    }());

    (function () {
        var num = 100;

        function menu() {
            alert(num);
        }
    }());
	//결과로 200이 출력됨
</script>

객체 생성자 함수

내장 객체를 생성할 때는 이미 자바스크립트 엔진에 내장되어 있는 객체 생성자 함수를 이용하여 객체를 생성한다.

<script>
   function CheckWeight(name, height, weight){
        //매개변수 name,height,weight를 객체생성자함수라고 함
       //생성한 객체에 이름,키,몸무게 속성을 등록
       this.userName = name;
       this.userHeight= height;
       this.userWeight=weight;
       this.minWeight;
       this.maxWeight;
       
       //생성한 객체에 각 속성값을 출력하는 함수등록
       this.getInfo=function(){
           var str="";
           str += "이름 : "+this.userName +",";
           str += "키 : "+this.userHeight+",";
           str += "몸무게 : "+this.userWeight +"<br>";
           return str;
       }

       //정상몸무게,표준오차 몸무게를 구하여 몸무게가 정상인지 출력
       this.getResult=function(){
           this.minWeight=(this.userHeight-100)*0.9 -5;
           this.maxWeight=(this.userHeight-100)*0.9+5;

           if(this.userWeight >= this.minWeight && this.userWeight <= this.maxWeight){
               return "정상 몸무게입니다";
           }else if (this.userWeight < this.minWeight){
               return "정상 몸무게보다 미달입니다."
           }else{
               return "정상 몸무게보다 초과입니다."
           }
       }
   }

   //new키워드로 객체생성
   var jang = new CheckWeight("장보리",168,62);
   var park = new CheckWeight("박달재",180,88);
   console.log(jang);
   console.log(park);

   document.write(jang.getInfo());  //이름 : 장보리,키 : 168,몸무게 : 62

   document.write(jang.getResult());  //정상 몸무게입니다
</script>

메모리 절약을 위한 프로토타입 사용하기

앞에서 배운대로 객체를 생성하면 객체를 생성한 만큼 함수가 등록이 된다.
하지만 함수를 계속 늘린다면 메모리공간을 많이 차지하게 될 것이다.
이럴때는 객체 생성자에 프로토타입을 사용하여 함수를 등록하면 메모리낭비를 줄일 수 있다.

아래 예제는 객체를 생성할 때 프로토타입으로 함수를 등록하는 예제이다.

<script>
    function CheckWeight(name, height, weight) {
        //생성한 객체에 이름,키,몸무게 속성을 등록
        this.userName = name;
        this.userHeight = height;
        this.userWeight = weight;
        this.minWeight;
        this.maxWeight;
    }
    //프로토타입으로 함수등록
    CheckWeight.prototype.getInfo = function () {
        var str = "";
        str += "이름 : " + this.userName + ",";
        str += "키 : " + this.userHeight + ",";
        str += "몸무게 : " + this.userWeight + "<br>";
        return str;
    }

    //프로토타입으로 함수등록
    CheckWeight.prototype.getResult = function () {
        this.minWeight = (this.userHeight - 100) * 0.9 - 5;
        this.maxWeight = (this.userHeight - 100) * 0.9 + 5;

        if (this.userWeight >= this.minWeight && this.userWeight <= this.maxWeight) {
            return "정상 몸무게입니다";
        } else if (this.userWeight < this.minWeight) {
            return "정상 몸무게보다 미달입니다."
        } else {
            return "정상 몸무게보다 초과입니다."
        }
    }

    var jang = new CheckWeight("장보리", 168, 62);
    var park = new CheckWeight("박달재", 180, 88);
    console.log(jang);
    console.log(park);

    document.write(jang.getInfo());
    document.write(jang.getResult(), "<br>");

    document.write(jang.getResult === park.getResult)
    //true 객체가 같은 함수를 쓰고있다
</script>

좋은 웹페이지 즐겨찾기