All Articles

속깊은 JavaScript - 자바스크립트의 변수

본 포스팅은 양성익님의 속깊은 Javascript를 읽고 정리해본 글입니다.

image.png

변수에 대해선 위코드 1주차때 한번 정리한적이 있는데, 속깊은 자바스크립트(이하 속깊자) 3장 내용이 마침 변수에 대한 거라서 다시한번 정리 고고!
지난번 포스팅은 스크롤을 좀만 내리면 링크를 걸어놨다~

자바스크립트 기본형과 typeof

자바스크립트의 기본형 변수에는 여섯 가지가 있는데

  • number
  • string
  • boolean
  • undefined
  • null
  • symbol

위의 것들이 기본형 변수이다.

JS는 이러한 기본형 변수들과 Object를 기초로 하는 객체들로 구성되는데, 특정 변수가 어떤 형태인지 확인하는 연산자로 typeof 를 사용한다.

typeof true // boolean
typeof undefined // undefined
typeof null // object

희한하게 null의 type을 살펴보면 object이다.
자바스크립트 세상에선 null이 기본형으로 구분 되어있지만 왜 type은 object일까?
JS가 개발되었을 당시, 타 언어들과 마찬가지로 null이면 0이라는 값을 가지는 객체로 취급해서 개발을 했는데 typeof null의 결과값을 null로 바꿔버리면 이미 만들어진 웹페이지들에 영향을 주기 때문에 결국 수정은 안했다는 소문이..

new String("")과 "", String("")의 차이

이게 뭔지 알아보기 전에 먼저 instanceof에 대해 알아보자.

왼쪽이 instanceof 오른쪽이니

윗줄의 코드처럼 보통 두 개의 인자를 받으며, 왼쪽에 받는 인자가 오른쪽에 받는 인자의 인스턴스인지 확인하고 맞으면 true, 아니라면 false를 리턴한다.

function Macaron (name, flavour) {
  this.name = name;
  this.flavour = flavour;
}

let gift = new Macaron("veryVeryStrawBerry", "strawberry");

console.log(gift instanceof Macaron); // true
console.log(gift instanceof Object); // true
console.log(typeof gift); // 'object'

여기서 알아둬야 할 점은 instanceof는 기본형에 대해선 동작하지 않는다는 점!

console.log(true instanceof Boolean); // false
console.log(22 instanceof Number); // false
console.log([0,1,2] instanceof Array); // true

왜냐? 배열을 생성하는 표현식은 내부적으로 new Array()와 같은 형태를 취하기 때문 string도 한번 확인해볼까?

const color1 = new String('blue')
const color2 = "blue"

console.log(color1); // [String: 'blue']
console.log(color2); // 'blue'
console.log(color1 === color2); // false
console.log(color2 instanceof String) // false
console.log(color2 instanceof Object) // false

color1과 color2는 똑같은 파랑이지만 완전히 같진 않다. 물론 === 말고 느슨한 비교를 하면 동일하다고 나오긴 하지만, 약간 생긴것도 다르다. 그래서 일반적인 string이 String 클래스의 인스턴스가 될수없다.

근데 기가 막힌건 이거다!

console.log(color1.constructor === String) // true
console.log(color2.constructor === String) // true

color2의 constructor가 String이라고..? String의 인스턴스는 아니였는데 얘 뭐지…
얘의 생성자가 String인 이유는 color2.constructor를 생성할때 내부적으로 형변환이 일어나는데 그 다음에 constructor에 접근하기 때문이라고 한다.

이게 내부 스크립트상 돌아가는 내용에 대해선 책에 자세히 나와있다. 책 사세요~

글로벌 변수

사실 글로벌 변수를 쓰는걸 지양하기 위해 자바스크립트에서 let과 const가 나오게 됐는데 왜 글로벌 변수를 쓰는게 위험한지 지금부터 알아보자!

일단 JS는 웹에서 쓰인다는 특수성을 가지고 있고, 웹과 다른 애플리케이션들의 차이점에는

  • 소스와 데이터의 공개성과 다양한 라이브러리 등 외부 소스 활용
  • 비동기 로직과 이벤트 기반 처리
  • PC부터 모바일까지 다양한 브라우징 환경

이렇게 세 가지가 있는데, 지금부터 글로벌 변수를 쓰면 안되는 이유와 함께 특징을 살펴보자

첫번째와 두번째 이유로 글로벌 변수를 쓰게 되면 충돌이 나게 된다.
세번째 이유는! 변수 메모리 관리 차원에서 쓰지 않기.
웹 페이지가 떠 있는 한 모든 글로벌 변수가 메모리에 상주해서 컴퓨팅자원이 소모된다.
여기서 나오는 개념이 바로 garbage collection이다.

Garbage Collection

image.png

자바스크립트는 변수의 메모리 관리 전략으로 자바의 garbage collection을 사용한다.
그래서 해당 변수를 참조하는 다른 변수나 함수가 있다면 메모리에서 해제하지 않는다.
JS에서 딱 한번만 순차적으로 실행되고 다시 호출될 일이 없으면 글로벌 변수들은 자신을 참조하는 다른 변수나 함수가 없어서 메모리에서 해제쓰~

하지만 JS는 이벤트 콜백 함수가 많이 사용되서 글로벌 변수는 하나 이상의 함수에서 참조할 확률이 높다. 또, 동적 변수 참조가 가능해서 하위 스코프가 살아있다면 상위 변수들도 계속 참조할 수 있는 상태로 남아 있게 된다.

그래서 모바일 브라우저의 메모리 사용을 원활하게 하기 위해 잠시 사용할 변수는 로컬변수로 현재 스코프에 올려서 사용하고, 사용 안 할 때는 해제하는 게 좋다.

window 객체

다른 언어와 다르게 자바스크립트는 글로벌 영역도 하나의 변수로 정의해서 사용하고 있다. 이 글로벌 영역은 window 객체가 관장하고 있는데, 과연 무엇일까! 이번 기회에 한번 제대로 알아보자.

먼저 Global Object는 어떠한 컨텍스트가 실행되기 전에 먼저 생성 된다.
생성자가 없어서 new로 생성할 수 없으며, 함수로 호출할 수도, 프로토타입도 없다.
HTML DOM환경에서 이 객체는 window 속성을 가지고 있으며 이게 바로 Global Object 그 자체!

image.png

이렇게 재귀적인 패턴도 엿볼 수 있다.

글로벌 변수 선언 방법

글로벌 변수 선언방법은 아래의 네 가지 방법이 가장 대표적이라고 한다.

  • 글로벌 스코프에서 var 써서 변수 선언
  • 상위 스코프에서 같은 변수명으로 선언되지 않고 var없이 바로 변수 사용
  • window 객체가 재건언되지 않은 스코프에서 window.global과 같이 속성 추가
  • window 객체가 재선언되지 않은 스코프에서 window[“global”]과 같이 속성 추가

image.png

선언자 없으면 변수 선언 못할줄 알았는데 되네? 신기신기

글로벌 변수 선언 방법의 차이

이건 지난번 포스팅에 써 놓은 내용을 참고하면 좋다. 지난포스팅이 궁금하다면 여기 클릭!!!

급하게 끝내는 것 같지만.. 정리하자면!

  • 다른언어에서처럼 자바스크립트에서도 글로벌변수 사용 자제하자
  • window객체는 글로벌 스코프의 변수들을 속성으로 가지고 있다
  • 선언자 없이 변수 선언시 글로벌 변수가 될 위험성이 있다
  • 스코프가 생성되면 선언자 하나에 변수들을 정의하는게 좋다
  • 글로벌 변수 사용을 최소화하기 위해 클로저나 모듈패턴을 사용하자
  • 상위 스코프에 있는 변수나 속성의 속성을 여러번 접근하는 경우 로컬 변수에 할당해서 사용하자

Reference

  • 속깊은 Javascript(양성익 저)