스코프 / 호이스팅 / 클로저

PYG·2021년 4월 27일
0

JAVASCRIPT

목록 보기
7/9

Scope(스코프)

  • 참조 대상 식별자(변수, 함수 이름)를 찾아내기 위한 규칙
  • 유효 범위
  • scope는 범위 즉 Javascript에서는 변수에 접근할 수 있는 범위
  • 함수를 선언할 때마다 새로운 스코프를 생성
  • 스코프는 함수를 호출할 때가 아니라 선언할 때 생성
  • 현재 자신의 scope(자신의 함수 안)에서 사용하고자 하는 변수가 없다면 Scope Chain을 통해 더 넓은 범위로 해당 변수를 찾게 된다
  • 함수 단위로 변수를 관리
    Javascript에서는 함수 블록 안에서만 var가 지역 변수가 된다
    for문 등에서 사용된 var은 지역 변수로 사용 X
    그래서 for문 안에 있는 var는 for문의 블록 밖에서도 사용 가능
  • 전역(global)변수를 만드는 일은 최대한 지양
    -전역 변수란 자바스크립트에서 제일 바깥 범위(함수 안에 포함되지 않은)에 변수를 만드는 것
    -window 객체에 변수를 만드는 것
  • 변수(var, let, const)로 선언을 해서 scope를 명확하게 해 주기
    -함수 안에 var, let, const 없이 그냥 변수를 선언할 경우 함수 밖에서도 참조 가능
    -사용할 변수를 되도록 함수 앞부분에 선언해두기
  • 루트 객체
    -모든 객체는 전역 객체라고도 하고 전역 변수 스코프라고도 한다
    -웹 페이지 실행 환경에서는 window가 루트 객체 (this === window)

1. 스코프의 두 가지 타입

  1. global(전역 스코프) : 어느 곳에서든지 해당 변수에 접근 가능 (어디에든 참조 가능)
  2. local(지역 스코프) : 그 지역에서만 접근 가능 (그 지역과 하부 지역에만 참조 가능)

function-level scope(함수 레벨 스코프) : 함수 안에 선언한 변수는 해당 함수 안에서만 접근 가능

-함수 내부에서 선언한 변수는 지역 변수 / 외부에서 선언한 변수는 모두 전역 변수

block-level scope(블록 레벨 스코프) : 함수를 선언할 때 중괄호로 함수 본문을 둘러싸게 되는데 이 부분을 블록이라고 한다

-함수, if문, for문, while문, try/catch문 등 내에서만 유효

2. scope chain(스코프 체인)

  • 내부 함수에서는 외부 함수의 변수에 접근이 가능하지만 외부 함수에서 내부 함수의 변수에는 접근 불가능
  • 현재 자신의 함수 안에 해당 변수가 없으면 outer 스코프에서 찾고 그래도 없으면 전역 스코프에 가서 찾는다
  • 이렇게 계속해서 범위를 넓히면서 찾는 관계를 스코프 체인이라고 한다

3. lexical scope(렉시컬 스코프, 정적 스코프)

  • 함수를 처음 선언하는 순간 함수 내부의 변수는 자기 스코프로부터 가장 가까운 곳(상위 범위에서)에 있는 변수를 계속 참조
var x = 1;
    function foo() {
    	var x = 10;
        bar();
    }
    function bar() {
    	console.log(x);
    }
foo();   ----> 1
bar();   ----> 1 

-> 1. 함수를 어디에서 호출했는가(동적 스코프 Dynamic scope) -- 함수 bar의 상위 스코프는 함수 foo와 전역
2. 함수를 어디에 선언하였는가(렉시컬 스코프) -- 함수 bar의 상위 스코프는 전역

4. 네임 스페이스

  • 변수의 이름이 겹치지 않도록 만드는 것
  • 전역 변수를 지양하는 이유는 변수가 겹칠 가능성이 있기 때문이다
  • 여러 명과 협동하거나 다른 사람의 라이브러리를 사용할 때 같은 변수 이름을 사용하게 되는 경우가 있다
  • 전역 변수 대신 함수 안에 넣어 지역 변수로 만들기
  • 고유의 네임 스페이스를 만들어 겹치지 않게 하기
var obj = {
  x: 'local',
  y: function() {
    alert(this.x);
  }
}

--> 겹칠 우려 최소화

클로저(Closure)

  • 함수 밖에서 선언된 변수를 함수 내부에서 사용할 때 클로저가 생겨난다
  • 내부 함수가 외부 함수의 맥락에 접근할 수 있는 것
  • 내부 함수는 외부 함수의 지역 변수에 접근 가능
  • 외부 함수가 더 이상 사용되지 않아도 내부 함수는 외부 함수의 변수에 접근 가능
  • 클로저는 객체의 메소드에서도 사용
  • 함수와 함수가 선언된 어휘적 환경의 조합
  • 오직 하나의 메소드를 가지고 있는 객체를 일반적으로 사용하는 모든 곳에 클로저를 사용 가능
  • 비공개 내부 변수를 갖는 함수 인스턴스 생성자
  • 클로저로 생성한 독립된 변수 공간을 가진 인스턴스를 클로저 인스턴스라고 한다
  • 함수 내부에서 함수를 선언할 때 내부의 함수를 클로저
  • 클로저는 외부 함수에서 생성된 변수들에 접근할 수 있는 권한을 가짐

return은 한 번 출력하면 그 함수는 생을 마침
-그렇게 되면 함수 안의 지역 변수 값은 함수 종료와 함께 사라지기 때문에 그 값을 보존하기 위해 클로저가 생김
private valuable 사용 시 get, set 메소드
-get은 가져오는 것, set은 수정하는 것

  • 클로저에 있는 세 가지의 스코프
    -전역 범위(global scope)
    -지역 범위(local scope)
    -외부 함수 범위(outer functions scope)

호이스팅

  • var, function 선언들이 자동적으로 제일 위로 올라가는 것
  • 변수의 사용 및 함수의 실행 코드가 선언보다 먼저 일어나도 정상 진행이 되도록 해주는 것
  • 선언과 초기화가 동시에 같이 명시되면 에러 발생
  • 초기화 코드는 반드시 실행 코드보다 먼저 있어야 한다
  • 함수 내에서 아래쪽에 존재하는 내용 중 필요한 값들을 끌어올리는 것
  • 함수 내에서 선언한 함수 범위(함수 스코프)의 변수는 해당 함수의 최상위로
  • 함수 밖에서 선언한 전역 범위(글로벌 스코프)의 전역 변수는 스크립트 단위의 최상위로
  • 작성한 코드 내에서 var보다 위에 적힌 함수가 var 변수 선언을 인식해서 함수 범위의 최상단으로 끌어올려 밑에 있는 var 변수 선언에도 함수를 적용시켜 주는 것
  • var 변수 선언과 함수 선언문에서만 호이스팅 발생
  • 선언만 위로 올려지고 할당은 끌어 올려지지 않는다
  • let, const, 함수 표현식에서는 호이스팅 발생 X --> 에러 발생
  • 코드의 가독성과 유지보수를 위해 호이스팅이 일어나지 않도록 한다
  • 변수 생성 3단계
  1. 선언 단계 : 변수를 실행 컨텍스트의 변수 객체에 등록 (스코프가 참조하는 대상)
  2. 초기화 단계 : 변수 객체에 등록된 변수를 위한 공간을 메모리에 확보 (undifined로 초기화)
  3. 할당 단계 : undefined로 초기화된 변수에 실제 값을 할당
  • var 키워드로 선언된 변수는 선언 단계와 초기화 단계가 한 번에 이루어진다
    -따라서 변수 선언문 이전에 변수에 접근해도 스코프에 변수가 존재하기 때문에 에러 발생 X
    -다만 undefined를 반환 후 변수를 할당하면 그때 값이 할당된다 = 변수 호이스팅
  • let 키워드로 선언된 변수는 선언 단계와 초기화 단계가 분리되어 진행
    -초기화 이전에 변수에 접근하려고 하면 참조 에러(ReferenceError)가 발생
    -변수가 아직 초기화되지 않았기 때문 -> 변수를 위한 메모리 공간이 아직 확보되지 않았기 때문
    -스코프의 시작 지점부터 초기화 시작 지점까지의 구간을 ‘일시적 사각지대(Temporal Dead Zone; TDZ)라고 한다
var x = 0;
{
  var x = 1;
  console.log(x); // 1
}
console.log(x);   // 1
  • var는 함수 스코프를 따른다
  • 첫 번째로 선언된 x와 두 번째로 선언된 x 모두 메인 함수의 전역 공간에 선언되어 있는 것
  • 두 번째로 선언된 x가 값을 덮어 씌운 것
let y = 0;
{
  let y = 1;
  console.log(y); // 1
}
console.log(y);   // 0
  1. 함수 선언문(function declarations) : function 명령어와 함께 함수명을 지정하고 function body 내용을 구성하는 것
function foo() { 
	console.log("hello");
    }
  1. 함수 표현식(function expresstions) : 변수에 함수를 할당하는 형태의 함수 표현식
var foo2 = function() {
	console.log("hello2");
    }

호이스팅의 우선 순위

  • 변수 선언 > 함수 선언

1.1 같은 이름으로 변수와 함수를 선언하면

var abc = "hi";
  function abc() {
      console.log("bobo");
  }
  function efg() {
      console.log("gogo");
  }
  var efg = "bye";
  console.log(abc);
  console.log(efg);

-> 값은 hi, bye

0개의 댓글

관련 채용 정보