1. 원시자료형(Primitive)과 참조 자료형(reference)
- 원시 자료형 : number, string, boolean, null, undefined처럼 박스의 이름을 선언하고,
이름을 호출 하면 안에 담긴 내용이 나온다.
- 참조 자료형 : array, object처럼 박스의 이름을 정하는 것이 아닌, ''박스들이 모여있는 창고'의 '주소' (heap)을 적어놓고,
호출 시 그 창고의 주소를 찾아가서, 안의 박스의 내용물을 꺼낸다.
- 뭐가 다르죠? : 원시타입은 '하나의 덩어리'로, 저장해서 불러오기 한다. 하지만 참조 타입은
자료 자체가 하나의 덩어리가 아닌, 각각의 자료들로 저장되기 때문에, 자료의 길이나 종류가 많아지면 저장공간이 너무 늘어나고, 자료를 따로 수정하기가 곤란하다.
그래서 큰 창고에 박스들에 자료를 담아두고, 그 창고 주소만을 불러오게 된다!
- 그게 왜 중요하죠? : 각 자료들을 복사했을 때, 원시 자료형은 기존의 자료와 복사본은 별개로 움직인다.
각각 다른 것들이 된다. 하지만, 참조 자료형은 복사한 자료의 '주소'를 복사했기 때문에 자료를 수정하면 주소 안의 원래 자료도 수정된다!! : 그래서 우리는 resullt를 string이나 number로 선언 해 놓고,
result = result + '계산 한 값'을 제할 당 하여 result를 반환한 것이다!
- ! : 그래서 우리는 slice로 잠깐! 배열이나 객체를 복사해 수정한 후, 반환할 수 있다!
원본 배열이나 객체는 바뀌지 않았다!
2. 스코프
- 내가 보는 범위를 정해준다!
- 즉, 스코프는 괄호(if나 for나, function) 안의 범위를 말한다. 그 밖으로 가면 그 안에 선언된 변수 등은 접근이 불가능하다.
- 반대로 스코프 밖에서 선언된 것들은 계속 사용이 가능하다!
- 그러므로 스코프들에서 선언된 변수들은 스코프를 울타리로 만들어서 계속 쌓여간다. 울타리 안으로 올 수록 더 높은 우선순위가 된다
- 전역 스코프 : 가장 밖의 울타리
- 지역 스코프 : 전역 스코프의 안쪽에 있는 스코프 들
- 선언을 함수 안에서 하면, 함수 안에서만 작동하는 변수가 되고,
- 선언이 밖에서 된 체로 들어와 함수 안에서 제할 당 되면 함수를 빠져나오고 나서도 계속 제할당 된 체로 살아간다.
- - 주의! : 함수 밖에서 선언된 것이, 함수 안으로 들어와 다시 할당되는 경우
3. 스코프의 종류
- block scope : 중괄호를 사용해 범위를 정해줌 (if 나 for)
- function scope : 말 그대로, 함수 스코프. 함수의 범위를 정해준다.
- '화살표 함수'는 블록 스코프가 된다.
- 화살표 함수..? : function 빼고 식별자 선언해 주고 소괄호와 중괄호 사이에 넣어서 함수를 만든 것.
- 'var' 키워드를 사용하면 블록 스코프 안에 선언된 변수를 블럭 스코프 밖에서도 사용할 수 있다. 하지만, 헷갈리니까 'let'을 사용하자.
- let은 매우 안전한 키워드다. 변수가 재선 언 되는 경우를 막아주기 때문이다.
- 사실 브라우저에서는 'window'라는 객체를 가지고 있다. var은 window에 속한다.
- 'const' 키워드를 사용하면 변수의 값을 변하지 않게 할 수 있다.
- let과 마찬가지로 재선언을 막아주며, 재할당 까지 막아버려 값의 변화를 최소화시켜 안전한 프로그램을 만들 수 있다.
- 전역 변수에 너무 많은 것들을 넣지 말자. 예측할 수 없는 문제들이 발생하고, 헷갈린다. 심지어 여러 명이 작업했다면 더더욱... 전역 변수를 줄이는 활동을 side effect라고 한다.
- Strict Mode : 브라우저에서는 'use strict'; 를 첫 번째 줄에 적어서 선언이 없는 변수를 오류로 보게 할 수 있다!
4. 클로저
클로저를 알기 위해서는 먼저, 어휘적 환경을 알아야 한다.
- 어휘적 환경( Lexical Environment) : 함수가 선언되면 그 함수의 스코프 안에서 변수를 찾아 사용한다. 하지만 그 스코프 안에 변수를 찾을 수 없다면, 그 스코프의 밖의 스코프로 가서 다시 변수를 찾는다. 이렇게 전역 스코프까지 가서 변수를 찾게 된다. 이때, 우리는 그 환경을 어휘적 환경이라고 한다.
- 클로저 : 아래의 예시로 함수가 두 개인 경우를 보면 알 수 있다.
const adder = function (x) { // 변수 x를 먼저 선언 하면서 외부 함수를 만듬.
return function (y) { // 그 안에 또 다른 함수를 반환.
return x + y; // 이때, 내부 함수 안에 y는 있지만, x를 외부에서 가져옴.
} // 내부의 y는 외부에서 사용할 수 없지만, 외부에서 선언한
} // x는 사용가능! 이때 x가 클로저 함수가 됨.
- 왜 클로저를 사용합니까? : 외부 함수의 실행이 끝나 값을 반환해도, 또다시 외부 함수의 변수를 사용할 수 있기 때문!
- 선언한 변수와 함수를 꽁꽁 숨겨서 프로그램이 다른 프로그래머들이 보수했을 때도 오류를 발생하지 않게 한다. 일명, 정보의 '캡슐화'로 전역 변수를 최대한 줄인다.
- 특정한 데이터를 스코프로 가두어서 계속 사용할 수 도 있다! 하나의 함수를 계속 사용해서 효율적으로 데이터와 메서드를 다룬다. 일명, '모듈화'
간단하게 말하면, 외부 함수의 변수에 접근할 수 있는 내부 함수...
의 특징을 가지고 있는데 이렇게 말해도 된단다.
여담 : 내 생각에 클로저는 함수 자체를 변수로 선언해서, 그 함수가 끝나도 다시 변수가 된 함수를 가져와서 계속 쓰는 것 같다. 그래서 'Closure' 일명, 닫친 거 즉, 범위를 정해준 느낌이 든다. 함수는 자신의 스코프가 닫치면 더 이상 선언된 것들을 사용하지 못한다. 그래서 그 닫은 범위를 들고 다니면서 다음에도 사용할 수 있도록 만들어 주는 느낌? 이 든다. 사실 뭔가 시원하지가 않다. 더 알아봐야 할 것 같다.