Scope와 Closure

이동환·2020년 8월 5일
1

TIL

목록 보기
8/74

Scope

: 한국어로 '범위'라고 한다. 코드에서 범위란 코드들이 활용되어 질 수 있는 범위를 뜻한다.

코드를 작성하면 자동적으로 범위가 정해진다. 이 범위가 자동적으로 작성되어질때, 큰 역할을 하는것은 선언할때 씌여지는 let, const 그리고 var가 있다. 이 3가지를 설명하기 전에 먼저 Global scope와 Local scope를 이해하면 좋을것 같다.

Global scope vs Local scope

  1. Global
    : 전역범위라고 부른다. 말 그래도 전역, 즉 파일에서 전역으로 사용되어 질 수 있는 것이다.
  1. Local
    : 전역과 반대되는 개념으로 지역 범위라고 부른다. 여기서 지역이란, block 단위라고 보면 될거 같다. 다시 말해, 함수나 객체와 같이 {}라는 블록안에서만 효력을 발휘한다.

두가지의 이해를 돕기위해, 좋은 예가 있다.

let name = 'Donghwan';
function showName(){
  let name = 'Lee';
  console.log(name);
}
//
console.log(name);
showName();

위와 같은 코드를 작성했을때,
console.log(name)은 'Donghwan'을 출력하고,
그 아래 있는 showName()은 'Lee' 를 출력한다.

여기서 잘 주의해야 할 것은 첫줄에 적힌 let name = 'Donghwan'; 은 function showName 위에 서로 분리되어 선언이 되어있다는것이다.

먼저 선언된 let name = 'Donghwan';은 아무런 블럭( {} )안에 들어가 있지않다. 그렇기에 저것은 '전역 변수'라고 부른다. 반면에 함수안에서 선언된 let name = 'Lee';은 { } 라는 블럭안에서 선언되어있기에 함수 showName에서만 사용되어질 수 있는 '지역변수'인것이다.

아직 이해가 가지않는다면, 이를 '법'으로 비유를 해보면 좋을것같다. 전역이란 국제법과 같은것이고, 지역은 국법이라고 생각하면 이해가 쉬울거같다. 국제법은 전체적으로 영향력을 미치지만, 특정 나라에서는 그 나라법이 먼저다. 로마에 가면 로마의 법을 따르라는말이 있듯이 블럭안에서는 국제법이고 뭐고 지역의 변수를 최우선으로 생각하면 된다.

let vs const vs var

이 3가지는 변수를 선언하는데 사용되어진다. 위에서 말했듯이 무엇을 사용하느냐에 따라 지역변수인지 전역변수인지를 판단이 되어진다.

  1. let
    : 먼저 let이다. let은 Block scope라고 한다. 위에서 봤던 예처럼 작동한다. 블럭에 들어가 있으면, 지역변수가 되어지는것이고, 블럭에 위치하지 않으면 전역변수가 되어지는것이다. 추가로 let을 사용하면 같은 변수로 재선언이 불가능하다. 그렇지만 변수값은 재정의 할 수 있다. 이 개념은 const와 반대되는 개념이다.

  2. const
    : const 역시 Block scope이다. let 처럼 작동하지만, 이 둘의 차이점은 값을 재정의 할 수 있는가 아닌가로 나뉘어진다. let은 한번 정의된 값을 재정의가 가능하지만 const는 불가능하다.

  3. var
    : 가장 먼저 말하고 싶은것은 var 사용을 권장하지 않는다는것이다.
    아주 old-fashion한 방법이라고 말하고싶다. 그 이유는 먼저 무조건 전역변수로 만들어주기 때문이다. 함수 안에서만 사용하고 싶은 변수가 전역에서 사용되어질 수 있다고 생각하면 많은 오류를 야기할 거라고 생각이 든다.

위에서 했던 말을 간단하게 표로 작성했다. 사실 표만 보고 숙지해도 좋을것 같다.

전역 변수와 window 객체

  1. window란
    : 전역범위를 대표하는 객체다. 개발자도구에 window를 치면 그에 맞는 키와 키값을 볼 수 있다.

  2. Global scope에서 선언된 함수와 var를 사용하여 선언된 변수는 window객체와 연결이된다.

  • 주의 사항.
    전역범위에 너무 많은 변수를 선언하면 좋지않다. 최대한 사용을 지양하자

선언없이 초기화된 전역변수

: 절대로 선언 할 때 사용하는 키워드없이 변수를 초기화 하지말자 !

ex)

funtion showAge(){
  age = 90;
  console.log(age);
}
//
cosole.log(age);    //90
showAge();          //90

위의 예처럼 let또는 const 없이 사용하면 age는 window객체로 들어가 전역변수로 사용되어진다.

'use strict'

위와 같은 상황을 방지하기 위해서, strict mode를 사용하자.
사용방법은 가장윗줄에 'use strict'만 적으면 끝.

'use strict'를 위와같은 똑같은 예시에 사용해보자
ex)

'use strict'
funtion showAge(){
  age = 90; // 여기서 에러가 발생(age is not defined)
  console.log(age);
}
//
cosole.log(age);   
showAge();          

Closure

: 외부함수의 변수에 접근 할 수 있는 내부 함수.(주의 해야할 점 : 내부에 함수가 있고, 리턴한다고해서 클로져라고 부르지 않는다. 외부함수의 변수와 관련되어있어야함.)
또한 클로져 함수는 지역변수,외부함수 그리고 전역변수에 다 접근이 가능하다는점도 알아두자.

유용한 클로져 예제

1. 커링
:함수 하나가 n개의 인자를 받는대신, n개의 함수를 만들어서 각각의 인자를 받게하는것.

ex1)
function add(x){
  return function (y){
    return x + y;
  }
}
add(2)(3)// 5 (x는 2, y는 3)
let add5 = add(5);
add5(3); //8
//
ex2)
function htmlMaker(tag){
  let start = '<' + tag + '>';
  let end = '<' + tag + '>';
  return function(content){
    return start + content + end;
  } 
}
let divMaker = htmlMaker('div');
//
divMaker(hi); // <div>hi<div>

2. 클로져 모듈
:변수를 스코프 안쪽에 가두어 함수 밖으로 노출 시키지않는 방법(private). 그렇지만 내장 함수를 사용하여 변경 시킬 수 있다.
또한 사용된 private 변수는 독립적으로 사용되어진다.

ex)
function counterMaker(){
  let privateCounter =0;
  return {
    increment : function(){
      privateCounter++;
    },
    decrement : function(){
      privateCounter--;
    },
    getValue : function(){
      return privateCounter;
    }
  }
}
let counter1 = counterMakter()
counter1.increment();// 1
counter1.increment();// 2
counter1.increment();// privateCounter === 3
//
counter2.increment(); // 1
counter2.decrement(); // 0
counter2.increment(); // 1
counter2.increment(); // 2
counter2.decrement(); // privateCounter === 1
// counter1과 counter2는 같은 변수 privateCounter를 
// 사용했지만 둘 다 0부터 시작하였다. 
// 이것을 우리는 변수 privateCounter는 독립적이다. 라고 말한다.

Koans 문제

Advanced를 풀며 새롭게 익힌 콜백 메소드.

1. filter (immutable)
: filter라는 말답게 테스트하여 true값을 얻은것에 한해 새로운 배열을 생성

const animals = ['dog','cat','rabbit','panda','koala'];
const result = animals.filter(function(animal){
  return animal.length > 3;
});
console.log(result); //['rabbit', 'panda', 'koala']

2. map (immutable)
: 배열 내의 모든 요소 각각에 대하여 주어진 함수를 호출한 결과를 모아 새로운 배열을 리턴한다.

let words = ['worker', 'de','nsole'];
const result = words.map(function(word){
  return `co${word}`;
});
console.log(result);  //["coworker", "code", "console"]

3. reduce (immutable)
:함수 결과에 따른 하나의 값만 리턴한다.

let numbers = [1,2,3,4,5];
let result = numbers.reduce(function(accumulator, currentValue){
  return accumulator + currentValue;
}, 100);
console.log(result); // 115
// 100 + 1 
// 101 + 2
// 103 + 3
// 106 + 4
// 110 + 5

4. every
: 배열의 요소 하나 하나가 모두 콜백함수의 조건을 통과하는지를 판별한다.
리턴값은 새로운 배열이 아닌 Boolean값이며 빈배열은 무조건 True를 리턴한다.

let nums = [1,3,5,7,9];
let odd = function(n){
  return n % 2 === 1
}
console.log(nums.every(odd));  
// true : 1,3,5,7,9 모두가 홀수여서 true를 리턴한다.

5. some
: 콜백 함수를 통과하는 어떤 요소라도 존재하면 true 값을 가진다.

let nums = [1,3,4,5,7,8,9];
let even = function(n){
  return n % 2 === 0
}
console.log(nums.some(even));  
// true : 4,8 이 짝수여서 true를 리턴한다.

6.forEach
:

profile
UX를 개선하는것을 즐기고 새로운것을 배우는것을 좋아하는 개발자입니다.

0개의 댓글