[JavaScript] JS심화-실행컨텍스트, this, 클로저

부지런한 배짱이🤟·2022년 4월 25일
0

공부기록

목록 보기
11/23

📍 오늘배운내용

  • 실행컨텍스트 (및 JS의 코드실행순서)와 this 에대해 알아보자
  • 클로저라는 개념 모를때는 우리가 사용하고 있었지만 개념으로 공부하니까 어려웠다!
    => 정말 간단하게 말하자면 함수가 종료되면 함수내부의 변수는 사라지지만 외부로 전달하여 사용가능한것을 클로저라고 하자
  • 일반함수와 화살표함수가 가르키는 this를 알아두기!

1️⃣ 실행컨텍스트 , Execution Context

1. 자바스크립트 함수가 실행되는 과정

자바스크립트 엔진은 코드가 없어도 3가지 변수를 포함해서 실행환경(실행컨텍스트)를 초기화한다.
1. this
- this 포인터의 경우, 글로벌 스코프에서는 window(global)를 가르킨다.
2. 변수들 (Variable Object)
3. Scope chain
- scope는 코드가 현재 실행되는 환경, 맥락을 의미한다.

📍 자바스크립트가 실행되면 전역 실행 컨텍스트(Global Exeuction Context)가 만들어지고 함수가 실행될때는 함수 실행 컨텍스트 (Function Execution Context)가 만들어진다.
📍 함수가 실행되면 함수 스코프에 따라 환경이 만들어지고 this, 변수, 스코프체인이 형성된다. 함수 실행이 끝나면 스코프 체인을 따라 글로벌 환경에 도달한다.

  • 어떤 코드도 없는경우(실행하는 함수) : 예를들어 html/css로만 구성된 웹을 브라우저에 실행할때

    console.log(this); //window 
    • this : window
    • 변수들 (Variable Object) : {}
    • Scope chain : []
  • 특정 함수가 존재하고 실행되는 경우

    function fac() {
    	let a = 100;
    	let b = 200;
    	
    	function mul (first, second) {
    		return first * second;
    	}
    	return mul(a,b)
    }
    
    //fac 함수 실행
    fac();
    Executive Contextfac()mul()
    thisundefined (strict mode - js 실행될때 정해진 mode..)undefined
    Variable Object{ a:100, b:200, mul:function{..} }{ first : 100, second : 200}
    Scope chainglobalfac, global
  • mul()은 실행이 끝나면 해당 실행컨텍스트는 모두 삭제되고 fac 스코프로 돌아간다.

  • fac 실행이 끝나면 원래 모두 삭제되고 실행되는 코드가 없던 상태로 돌아감(global 스코프로 돌아감!)

2. 실행 컨텍스트

  • 실행 컨텍스트 혹은 실행맥락은 자바스크립트 코드가 실행되는 환경
  • 코드에서 참조하는 변수, 객체(함수포함),this 에 대한 레퍼런스가 있다.
  • 실행 컨텍스트는 전역에서 시작해서 함수가 호출될때 스택에 쌓이게 된다.
  • 실행 컨텍스트 스택(call stack)
    • 스택의 자료구조 처럼 가장 나중에 실행된 함수의 실행컨텍스트가 가장 먼저 제거된다!

      let a =20;
      function func() {
      	let b= 30;
      	function check(v) {console.log(v)}
      	function func2() {
      		let c = 40;
      		check(a+b+c)//=========== 4
      	}
      	func2()       //=========== 3
      }
      func()       //============== 2
      
              //====================1
    • Global : a , console(전역객체이기 때문에), func함수

    • func 함수 : b, check함수, func2함수 (전역에서 func() 에 의해 실행)

    • func2 함수 : c (전역 > func() 내에서 func2() 에의해 실행)

      - check(a+b+c) 호출
      - 스코프체인을 따라서 해당 변수를 찾아나섬 (스코프 체이닝!)
      - ⇒ `a`는 `전역`에서 `b`는 `func`함수스코프에서 `c`는 `현재 스코프안` 에서 찾음
    • check 함수 : v (전역 > func() > func2내에서 check(a+b+c) 에 의해 실행)


2️⃣ this 가 가르키는것

1. dynamic binding

  • 함수 호출되는 상황은 4가지 상황
    • 함수 호출, 메서드 호출(객체의 메서드), 생성자 함수 호출(new 키워드), 간접호출(call, apply 등)
    • callapply 는 기본적인 function 의 객체
    • 그외 콜백함수의 호출이 있음 (특정 동작이후로 불려지는 함수, 다른 함수의 인자로 보내지는 함수)
  • bind, apply, call 등으로 this 가 가르키는 것을 조작할 수 있다!
    • bind(p) : thisp 객체를 가리키도록

2. 화살표 함수의 this 🆚 일반함수의 this 🆚 콜백함수 this

let o = {
  name: "zeeyoon",
  f1: () => {
    console.log("[f1] this :",  this);
  },
  f2: function () {
    console.log("[f2] this :",  this);
  },
};

o.f1(); // 화살표함수 global
o.f2(); // 일반함수  a

setTimeout(o.f1, 10); //콜백함수 global
setTimeout(o.f2, 20); //콜백함수 global

화살표 함수와 콜백함수로 함수를 실행할때는 기존의 맥락(this)를 전역 컨텍스트의 맥락으로 바꾼다.

📍 화살표 함수와 일반함수의 this

  • 화살표 함수의 this
    • 항상 상위 스코프의 this를 가르킨다.
    • 화살표 함수의 this는 정해지면 apply, bind, call 로도 조작할 수 없음
  • 일반함수의 this ⇒ 새롭게 생성된 실행 컨텍스트를 가르킴 (함수가 만들어진 환경의 스코프)
    • 메소드와 함수는 다르다! (간단하게 점 혹은 대괄호의 여부로 구분하기 > 있다면 메소드)
      1. 함수 실행 시에는, 전역(window)객체를 가리킨다.
      2. 메소드 실행 시에는 메소드를 소유하고 있는 객체를 가리킨다.
      3. 생성자 실행 시에는 새롭게 만들어진 객체를 가리킨다.
   const fac = {
     method() {
       console.log("context : ", this); //fac
       let func1 = function () {
         console.log("[일반함수 func2] this : " , this); 
       }
       let func2 = () => 
         console.log("[화살표함수 func2] this : " , this);
       
       func1(); // global
       func2(); // fac 화살표 함수이기때문에 호출된 위치인 method
     },
   };
   
   fac.method();
  • func1global을 가르키는 이유는?(⭐️⭐️⭐️⭐️)
    • func1 함수가 실행되면서 새로운 컨텍스트를 생성하는데 바인딩된 컨텍스트가 없으므로 thisgobal을 가르킨다.
  • method 내의 context: thisfac 인 이유는 global 에서 호출했을때 fac.method() 에 의해 global > fac() > method() 의 순서로 새로운 컨텍스트를 생성했기 때문임.

3. this를 조작하는 경우

let bio = {
  name: "zeeyoon",
  hello : function() {
    console.log("안녕 내이름은 ", this.name);
  },
};

bio.hello();    
//안녕 내이름은  zeeyoon (hello 의 this는 bio)

//콜백함수 > 전역객체를 바인딩한다
setTimeout(bio.hello, 10);   
//안녕 내이름은  undefined (hello의 this는 global)
setTimeout(bio.hello.bind(bio), 20);  //안녕 내이름은  zeeyoon  
// (hello의this를 global에서 bio 로 바인딩)

3️⃣ 클로저 , Closure

외부로 전달하는 방법

  • 전역 변수에 할당하기
  • return 값으로 외부로 전달하기
  • 자바스크립트에서 함수는 일급 객체 (first-class object)
    • 일급객체란, 다른 변수처럼 대상을 다룰 수 있는것
    • 즉 JavaScript 에서 함수는 변수처럼 다룰 수 있다.
    var f = function() {}
    // f 는 함수객체 -> 변수처럼 다룰 수 있음 
    
    const Bio = (name) => {
    	const hello = () => console.log("안녕 내이름은 ", name);
    
      return { hello } //객체처럼 
    	//return hello
    	//return hello()
    }
    
    const person = Bio('zeeyoon') //person 이라는 객체에 Hello 라는 함수 프로퍼티를 넣은것 
    person.hello();
    //bio('zeeyoon')();
    //bio('zeeyoon');
    

Closure 는 함수의 일급객체 성질을 이용한다 (JS)

  • 함수가 생성될 때, 함수 내부에서 사용되는 변수들이 외부에 존재하는 경우 그변수들은 함수의 스코프에 저장된다. (⇒ 원래는 실행이 끝나면 실행 컨텍스트가 삭제되기 때문에 변수도 존재하지 않는데 존재하는 경우)
  • 함수를 통해 외부로 그 값(변수)를 전달했을때 클로저가 가능하다!
  • 함수와 함수가 사용하는 변수들을 저장한 공간을 클로저(Closure) 라고 한다.
function createCV() {
  let name = "";
  let about = "";
  function changeName(txt) {
    name = txt;
  }
  function changeAbout(txt) {
    about = txt;
  }
  function print() {
    console.log("NAME : ", name);
    console.log("ABOUT : ", about);
  }

  return { changeName, changeAbout, print };
}

// 클로저 만들기 (외부에서 createCV함수 내부의 변수를  저장하는 공간 클로저를 만든다)
// 이력서 1
const cv1 = createCV();
cv1.changeName('zeeyoon');
cv1.changeAbout('개발 경력 6개월');
cv1.print(); //NAME :  zeeyoon ABOUT :  개발 경력 6개월

// 이력서 2
const cv2 = createCV();
cv1.changeName('june');
cv1.changeAbout('개발 경력 1년 이상');
cv1.print(); //NAME :  june ABOUT :  개발 경력 1년 이상

📍 코드 및 이미지 출처 : 엘리스 아카데미

profile
UX에 관심많은 프론트 엔드 개발자입니다:)

0개의 댓글