2. 변수, 호이스팅, 클로저

column clash·2021년 8월 16일
0

변수.

var fruits = "apple"
var fruits = "banana"

재선언가능

var fruits = "apple"
fruits = "banana"

재할당가능

function fruitsFunc() {
 var fruits = "apple"
 console.log(fruits); //apple
}
console.log(fruits) => error 

범위는 function


let, const

재선언 불가능.
let 재할당 가능, const 재할당 불가능.
block 레벨

ex)

function classFunc() {
	if (true) {
    	let myClass = "마케팅"
    }
    console.log(myClass) // error
}

호이스팅

//console.log(에이지);  //Uncaught ReferenceError: 에이지 is not defined
      console.log(나이); //error 안남. undefined 만 뜸.
      function 함수() {
        var 이름 = "kim";
      }
      if (true) {
        let 이름 = "park";
      }

      var 나이 = 30;
      console.log(나이); //30

왜 consoe.log(나이) 는 error 가 아니라, undefined 가 뜰까?

저코드는 자바스크립트가 이렇게 동작한다.

 var 나이;
      function 함수() {
        var 이름 = "kim";
      }
      if (true) {
        let 이름 = "park";
      }

      나이 = 30;

변수를 젤 위로 끌어올려서 선언부터 하고.
할당을 저렇게 하기때문이다.

자바스크립트는 변수나 함수를 선언하면
선언부분을 변수의 범위 맨위로 끌고가서
가장 먼저 해석한다.
그게 호이스팅이다.

변수여러개 선언

const 시간, 요금, 기간
const 시간 = "1hour", 요금 ="3000", 기간="1month"

전역변수

<script>
var 전역변수 = 20;
window.전역변수 = 20; 
</script>

같은거. window.전역변수 를 더 권장.

호이스팅함수

console.log(호이스팅변수);
var 호이스팅변수 = 20;
console.log(호이스팅변수);
function 호이스팅함수() {}
var 호이스팅변수;
function 호이스팅함수() {}
console.log(호이스팅변수);
호이스팅변수 = 20;
console.log(호이스팅변수);
함수();

      function 함수() {
        console.log(안녕);
        let 안녕 = "hello";   
      }
      
      // Uncaught ReferenceError: Cannot access '안녕' before initialization
      
      function 함수() {
        console.log(안녕);
        var 안녕 = "hello";   
      }
      
      undefined
함수();
var 함수 = function() {
	console.log(안녕);
    var 안녕 = "hello";
}
Uncaught TypeError: 함수 is not a function

function 함수() {
console.log(안녕);
    var 안녕 = "hello";
}
for (var i=0;i< 5;i++) {
setTimeout(function() {console.log(i)}, i*1000);
}  =>

결국 이런식이 되어서 참조하기때문에...
var i = 5;
for (var i=0;i< 5;i++) {
setTimeout(function() {console.log(i)}, i*1000);
}
 5 5 5 5 5

=>

let 으로 하면 block 레벨에서만 사용되기때문에..

for (let i=0;i< 5;i++) {
setTimeout(function() {console.log(i)}, i*1000);
}

0 1 2 3 4 

클로져

let saveNumber = 1;
function increament() {
	return saveNumber++;
}
console.log(increament());
console.log(increament());
console.log(increament());

1, 2, 3

=> 

let saveNumber = 1;
function increament() {
	return saveNumber++;
}
console.log(increament());
console.log(increament());

saveNumber = 200;
console.log(increament());

1, 2, 200

어딘가에서 갑자기 200 이 들어오면 ...
saveNumber 를 보호하고 있지 못하는 문제가
있다.

saveNumber 를 원천적으로 바깥쪽에서는 접근하지
못하게 할 수 있을까?


function increament() {
	let saveNumber = 1;
	return saveNumber++;
}
console.log(increament());
console.log(increament());
console.log(increament());
1
1
1

값이 증가하지 않는다.

이럴때 사용하는 자바스크립트만의 방식이 있다.
값자체를 반환하는 게 아니라 함수를 리턴을 해준다.

지금은 값자체를 반환시켜주는데 이 값을 함수로
감싸서 반환을 시켜준다.

function increament() {
	let saveNumber = 1;
	return function() {
    	return saveNumber++;
    }
}
함수는 값이 아니니까 호출해야 바로 이 값이 나올
수 있다. 반환된 함수를 변수에 저장해보자.

const inc = increment(); 

console.log(inc());
console.log(inc());
console.log(inc());
1
2
3


saveNumber = 1 로 기본값설정.
리턴을 하면서 이 saveNumber 는 사라진다.
함수안에 들어가있는 지역변수니까 사라진다.

inc() 를 부를때는
return function() {
return saveNumber++
}

를 반환. 그런데 어떻게 내부함수가 사라졌는데
1, 2, 3 이 반환되는 걸까?

이게 바로 클로져다.

클로저라고 하는 것은 함수 안쪽에서 함수가 만들어질때

increment 가 호출되면 increment 안에
들어와서 함수가 이때 반환하기 위해서 새로 만들어지는데

이렇게 만들어지는 상황에서
함수 안쪽에 있는 코드 중에
바깥 함수에 있는 변수에 접근을 하게 되면,

이 접근한 변수를 클로저라고 하는 특별한 공간에
저장을 해둔다.

그리고 나서 이 함수가 반환하면,
이 saveNumber 가 있던 increment 함수의
지역공간은 사라져서 내부변수 saveNumber 는
사라지지만

이 안쪽 함수가 만들어지면서 옮겨졌던 클로자라는
공간에는 여전히 saveNumber 가 유지되고 있는
것이다.

그래서 이 increment 함수가 호출될때,
이 saveNumber 는 어디서 찾아지느냐?

이 위쪽에 사라진 increment 의 로컬
공간에서 찾는게 아니라
클로저 공간에서 찾아서 저장된 값을 유지하면서
반환할 수 있게 되는 것이다.

increment 때 만들어졌다고 해서 이렇게 마킹도
나온다.

이렇게 특수한 공간 안에 바깥쪽에 있던 변수를
마치 가둬놓듯이 가둬놓을 수 있는 거이 바로
클로저라고 하는 공간이다.

클로저를 썼을 때의 장점은 무엇이 있을까?

지금 함수가 리턴되더라도 특정 값을 보호하면서,
그 값을 계속 사용할 수 있다는 장점이 하나
생겼다.

그래서, saveNumvber 가 1,2,3,4 계속
이렇게 증가한다.

그리고 또 하나 부수적으로 그 변수를 보호했기때문에
바깥쪽에선 어떤 방법으로든 saveNumber 를
접근할 길이 없다.

클로저 공간은 코드 상에서 접근할 수가 없기때문이다.

클로저 공간안에 있는 변수를 접근할 수 있는
유일한 길은 바로 이 클로저를 만든 함수안의 코드다.

근데 이 코드는 실행하는 순간,
즉, 런타임 상황에서는 바꿀 수가 없다.
우리가 코드에디터로.

그래서 완벽하게 보호되는 공간이다.

그래서 보호되어야하는 값이 필요하다면,
클로저 공간에 넣는 것들을 많이 사용하게 된다.

클로져의 뜻.

명세 : “A closure is the combination of a function and the lexical environment within which that function was declared.”
클로저는 함수와 그 함수가 선언됐을 때의 렉시컬 환경(Lexical environment)과의 조합이다.

풀이 :
자신을 포함하고 있는 외부함수보다 내부함수가 더 오래 유지되는 경우, 외부 함수 밖에서 내부함수가 호출되더라도 외부함수의 지역 변수에 접근할 수 있는데 이러한 함수를 클로저(Closure)라고 부른다.

한마디로 설명한다면: 즉, 클로저는 반환된 내부함수가 자신이 선언됐을 때의 환경(Lexical environment)인 스코프를 기억하여 자신이 선언됐을 때의 환경(스코프) 밖에서 호출되어도 그 환경(스코프)에 접근할 수 있는 함수

더 쉽게 한마디로 설명한다면 :
클로저는 자신이 생성될 때의 환경(Lexical environment)을 기억하는 함수다

클로져 알아보기 : https://poiemaweb.com/js-closure

profile
풀스택 개발 중...

0개의 댓글