자료형, 스코프, 클로저

Suxxzzy.log·2021년 11월 24일
0

자료형

원시 자료형과 참조 자료형

자바스크립트에서 변수를 선언하게 되면, 그 변수는 특정한 공간에 저장되게 된다.
그 공간은 변수가 어떤 유형이냐에 따라 종류가 달라지게 된다.

자바스크립트의 자료형은 크게 원시 자료형(primitive type)과 참조 자료형(reference type)으로 나뉘어지게 된다.
특히, 함수 연산 결과 부분에서 헷갈릴 수 있는데 이 부분에서 유의해야 할 것 같다.

원시 자료형

변수를 선언하고 할당할 때, 메모리에 그 변수에 대한 값을 직접 저장한다.
이러한 특징 때문에 아래 코드와 같은 결과가 나온다.
원시 자료형에는 string, number, bigint, boolean, symbol 등이 있다.

let a = 1;
let b = a;

console.log(a); //1
console.log(b); //1

b = 2;
console.log(a); // 1
console.log(b); // 2

//함수로 정리한다면 다음과 같겠다.
let a = 80;
function num(value){ //value 변수 선언하고 a값 할당.
  value = 90; //value 값을 90으로 변경
}

num(a) // 80

참조 자료형

참조 자료형은 대량의 데이터를 다뤄야 하는 상황에서 적합하다. 예를 들어, 객체, 배열, 함수 등이 있다. 참조 자료형은 메모리 공간에 데이터를 직접 할당하기에는 관리가 곤란한 점이 있기 때문에, 힙이라고 하는 별도의 공간에 데이터를 저장하고, 힙 주소를 메모리 공간에 저장한다. 따라서 그 이 자료형을 불러올 때는 메모리의 주소값을 보고 힙 공간을 찾아가서 자료를 불러오게 된다.!! 정리하면 참조 자료형은 다음과 같은 특징을 가진다.

//특징 1
let arr1 = [1,2,3]
let arr2 = arr1 // 변수 arr2에 arr1의 주소값을 할당한다. (복사)

console.log(arr1) // [1,2,3]
console.log(arr2) // [1,2,3]

arr2[1] = 8;
console.log(arr1) // [1,8,3]
console.log(arr2) // [1,8,3]

arr2 = 3;
console.log(arr1) // [1,8,3], arr1에는 변함이없다.
console.log(arr2) // 3

//특징 2
[] !== []
이것은 두 자료형이 주소값이 같지 않기 때문에 나타나는 현상이다.

//특징 3 
let a = {name : 1}
function num(value){ //value 변수 선언. a 대입 시 주소값 할당함. 
	value.name  = 3; // 3으로 변경되어 a의 것도 같이 변경됨. 
}

num(a) // 3

스코프

의미

스코프란 변수가 유효한 범위를 의미한다.

스코프 주요 규칙

  1. 전역 스코프의 경우에는 어떤 곳에서든지 참조를 할 수 있다.
  2. 내부 스코프는 외부 스코프에 있는 변수를 참조할 수 있지만, 외부 스코프는 내부의 변수를 참조할 수 없음에 유의한다.
  3. 변수가 같은 이름으로 선언이 된 상황이고 각각 내부, 외부 스코프에 들어간 상태라면, 내부 스코프에 있는 변수가 더 우선적으로 적용된다. 이를 연계하면 스코프 체이닝도 가능하다.
  4. 어느 스코프에서도 접근이 가능한 변수를 전역 변수(객체) 라고 한다. 브라우저의 window 객체가 대표적인 예인데, 이러한 점 때문에 전역 변수를 사용할 때는 유의하여야 한다. (의도하지 않게 윈도우 객체가 가진 키-값 쌍에 변경이 일어날 수 있기 때문이다)
//예1

let a = 4; //전역변수
function num(){
  let b = 7 ; //지역변수
  console.log(b) // 7
  console.log(a) // 4
}
  console.log(b) // ReferenceError : b is not defined
  console.log(a) // 4
  
이 같은 에러를 볼 수 있는 이유는 전역에서 지역변수를 찾으려고 했기 때문이다. 
지역변수 자체는 지역스코프에 선언, 할당되어 있지만, 전역에선 이를 참조할 수 없다.

//예2 : 스코프 체이닝(중첩)

let x = 10;
function num(value){
  x = 20
  console.log(x)
  
  function aka(foo){
    x = 30
    console.log(x)
  }
}   
console.log(x) //30

위의 경우에는 두 개의 함수 모두 자체적으로 x를 선언하지 않아서 전역에 있는 선언문을 찾아간다. 

//예3 : 스코프 체이닝(중첩)

let x = 10;
function num(x){ //변수 선언
  x = 20
  console.log(x) //20
  
  function aka(x){ //변수 선언
    x = 30
    console.log(x) //30
  }
}   
console.log(x) //10

이 경우는 함수 num, aka에서 자체적으로 변수 x를 선언했고, 리턴문이 없어 전역변수에 영향을 끼치지 않는다.

//예4 : 스코프 체이닝(중첩)

let x = 10;
function num(){
  x = 20 //선언문이 없으니 바깥 스코프로 가서 선언부를 찾는다. 20 재할당
  console.log(x) //20
  
  function aka(x){ //변수 선언
    x = 30
    console.log(x) //30
  }
}   
console.log(x) //20

//이 경우는 num에서 선언문이 없어 전역 변수에 있는 선언문을 이용하기 때문에 20이 출력된다.

block scope, function scope

블록 스코프는 변수가 유효한 { }의 영역이고,
function scope는 function 키워드가 붙은 곳에서 변수가 유효한 {}의 영역이다.
function scope는 함수 선언문과 함수 표현식만을 가리킨다.
(화살표 함수는 블록스코프로 봄)

let , const , var

let과 const는 var를 이용한 변수 선언으로 인해 생기는 문제를 개선하고자 추가된 변수 선언 방법이다.
각각의 특징은 다음과 같다.
let: 재선언 불가능, 재할당 가능
const: 재선언 불가능, 재할당 불가능( 선언과 동시에 할당 필요 )
var: 재선언 가능, 재할당 가능, 블록 스코프 무시(함수 스코프만 따름)

클로저(closure)

정의

클로저란 함수와 함수가 정의된 어휘적인 환경(context)을 의미한다고 한다..
문제 푸는 건 이해했는데 말 자체가 어렵다.
클로저를 이용하면 변수의 의도하지 않은 변경을 막을 수 있고,
함수의 재사용성 증대(모듈화), 캡슐화가 가능하다고 한다.

클로저 함수

클로저 함수란 자기 자신을 감싸는 외부 함수 스코프에 선언된 변수에 접근할 수 있는 내부 함수를 의미한다!!!! 꼭 기억할 것. 외변접내.

예를 들어 다음과 같은 곱하기 함수가 있다 치자.

function multi(num1){
  let a = num1
  return function (num2){
    	   return a * num2
         }
}   

즉 안쪽의 익명함수는 선언되지 않은 변수 a를 가지고 있는데, 스코프의 성질에 의해
바깥에 있는 선언된 변수 a에 접근한다.

굳이

function multi(num1, num2){
  return num1 * num2
}

이와 같이 쓰지 않는 이유는, 외부 함수의 실행이 끝나더라도, 외부함수에서 선언했던 변수를 내부 함수에서 계속해서 이용할 수 있기 때문이고,
외부함수에서 선언한 변수는 스코프 때문에 , 스코프 바깥의 함수에 영향을 받지 않는다는 장점이 있다.
이를 이용하여 함수의 재사용성을 높이는 과정을 모듈화라고 하고, 다른 함수에서 변수를 접근하지 못하도록 막는 과정을 캡슐화라고 한다.

profile
몫을 다하는 사람

0개의 댓글

관련 채용 정보