Variable
let
- mutable data type, can change contents
- Support from ES6+
- rw(read/write)
// added in ES5 , use this for Vanila Javascript 'use strict'; // Variable // let (added in ES6) // const (added in ES6) let name = 'dylan'; console.log(name); // name name = 'hello'; console.log(name); // hello
ES6에서 도입된 let을 사용하면 변수에 값을 재 할당하는 것이 가능하다. 변수(name)을 선언하게 되면, 그 변수 name은 값을 할당할 메모리의 한 공간을 가리키게 된다.(포인터와 같은 역할)
값을 할당하게되면, ‘dylan’이라는 값이 변수 name이 가리키고있는 메모리에 할당되는 것이다.
constant
- favor immutable data type always for a few reasons:
- security (악의적인 목적으로 변수의 내용을 바꾸는 것을 방지)
- thread safety (다양한 쓰레드들이 동시에 변수에 접근해서 값을 변경하는걸 방지)
- reduce human mistakes
- r(read only)
- use const whenever possible
- only use ‘let’ if variable needs to change
constant는 값을 한번 할당하면, 값을 바꿀수 없음(immutable)
앞으로 변경되어야할 이유가 없다면 왠만하면 const를 이용해서 작성하는게 좋다 ! (그렇게 해야 내가 나중에 코드 변경시, 혹은 다른 개발자가 코드를 변경할때 실수를 방지할 수 있다)
Block scope
let globalName = 'global name'; // global scope, 어느곳에서나 접근 가능 { let name = 'dylan'; //block scope, 블록안에서만 접근가능 console.log(name); // name console.log(globalName); // global name } console.log(name); // 아무것도 출력되지 않음 console.log(globalName); //global name
글로벌한 변수들은 어플리케이션이 실행되는 순간부터 끝나는 순간까지 메모리에 탑재되어있기때문에 필요한 부분에만 쓰는 것이 퍼포먼스에 좋다.
가능하면, 클래스나 함수, if 나 for loop 필요한 block scope에서만 정의해서 사용하는 것이 좋다.
‘var’를 더이상 쓰면 안되는 이유
- ES6의 ‘let’이 나오기 이전에는 변수를 선언하기 위해 ‘var’ 를 사용했다. var에는 많은 문제가 있었는데, 대부분의 프로그래밍 언어에는 변수를 선언하고 값을 할당하는게 일반적이다. 근데 ‘var’는 변수 호이스팅(Hoisting)으로, 선언하기 이전에 값을 할당하는 것이 가능하다. 심지어 값을 할당하기전에 출력하는 것도 가능하다.(할당하기 전에 출력하면, undefined로 나옴). 즉, var hoisting 이란, 어디에 선언했느냐에 상관없이 선언을 항상 맨 위로 끌어올려주는 것을 의미한다.
- var는 block scope가 없다. 즉, var로 선언하면 어느 영역에서나 호출이 가능하다. 모든걸 전역 변수로 선언하는 것은 메모리 낭비이다.(모두 전역 변수로 선언되는 것)
- 값을 재할당하는 것이 자유로워서, 왠지 모를 곳에서 오류가 발생할 확률이 높다…
Compatibility(호환성)
크롬, 파이어폭스, 사파리 등 대부분의 메이저 브라우저들이 지원하고 있지만, 인터넷 익스플로러만 지원을 하지 않는다. 전 세계에서 1%도 안되는 사용자들이 사용하고 있는 브라우저이기 때문에 신경쓰지 않아도 된다. 꼭 지원을 해야한다면, BABEL을 이용하여 ES6+로 개발 이후, 배포 이전에 다운그레이드 시키는 방법을 사용한다.
Variable types
C언어나 Java의 경우에는 데이터 타입이 다양하다.(메모리를 조금 더 효율적으로 관리할 수 있다는 말) 또한, 데이터 타입에 소수점일 경우에는 float을 사용해야한다.
(ex) 한 반의 학생수 변수를 선언할때 굳이 long(8bytes)로 선언하지 않고 short(2bytes), int(4bytes)로 선언할 수 있다.
하지만 자바스크립트는 ‘number’ 타입만 이용해서 숫자를 할당한다. 심지어 number이라고 데이터타입이라고 선언하지 않아도 된다. 자바스크립트에서는 타입이 다이나믹 하게 결정됨
let a = 12; let b = 1.2; let c = '12';
- primitive, single item : number, string, boolean, null, undefined, symbol
- primitive(변수에 직접적으로 할당) 타입은 값 자체가 메모리에 저장됨
- object, box container
- 변수에 오브젝트를 할당하게 되면, ref를 통해서 실제로 값이 담겨있는 메모리를 가리키게 됨
- function, first-class function (function도 다른 데이터 타입처럼 변수에 할당이 가능, 함수의 파라미터 인자, 리턴도 가능)
// number - special numeric values: infinity, -infinity, NaN const infinity = 1 / 0; const negativeInfinity = -1 / 0; const nAn = 'not a number' / 2; console.log(infinity); //Infinity console.log(negativeInfinity); //-Infinity console.log(nAn); //NaN (not a number)
//string const char = 'c'; const brendan = 'brendan'; const greeting = 'hello' + brendan; const helloBob = `hi ${greeting}, type: ${typeof greeting}`); // template literals (string) console.log(`value: ${greeting}, type: ${typeof greeting}`); // value: hello brendan, type: string
//boolean // false: 0, null, undefined, NaN, ' ' // true: any other value const canRead = true; const test = 3 < 1; // true
//null let nothing = null;
// undefined let x;
// symbol, create unique identifiers for objects const symbol1 = Symbol('id'); const symbol2 = Symbol('id'); console.log(symbol1===symbol2); // false console.log(`value: ${symbol1.description}, type: ${typeof symbol1}`);
심볼을 사용하면 동일한 string을 할당해도 다른 값으로 만들어지기 때문에, 고유한 식별자를 만들때 사용한다.
const gSymbol1 = Symbol.for('id'); const gSymbol2 = Symbol.for('id'); console.log(gSymbol1 === gSymbol2); // true
다음과 같이 Symbol.for()를 사용하면, 안에 string이 같을 때 같은 값이라고 인식한다.
+ 추가)
최근에 bigInt 라는 데이터타입이 추가됨. 원래 number 타입은 (-2^53 ~ 2^53) 까지 표현가능하지만, bigInt 는 더 많은 숫자를 표현할 수 있다.
const bigInt = 123124129412809128912042412412n; //끝에 n을 붙임
최근에 추가된 기능이기도 하고, 크롬이랑 파이어폭스에서만 지원한다.
또, 이렇게 큰 숫자를 다룰일이 별로 없다.
Note!
데이터 타입에는 Immutable data type(변경 불가), Mutable data type(변경 가능)이 있다.
- Immutable data types: primitive types, frozen objects (i.e. object.freeze())
- Mutable data types: all objects by default are mutable in JS
Dynamic typing : dynamically typed language
다른 언어들과 달리 자바 스크립트는 선언할 때 어떤 타입인지 선언하지 않고, 런타임(프로그램이 동작할때)에서 할당된 값에 따라 타입이 변경될 수 있다.
let text = 'hello'; console.log(text.charAt(0)); //h console.log(`value: ${text}, type: ${typeof text}`);// value: hello, type: string text = 1; console.log(`value: ${text}, type: ${typeof text}`); // value: 1, type: number text = '7' + 5; console.log(`value: ${text}, type: ${typeof text}`); // value: 75, type : string text = '8' / '2'; console.log(`value: ${text}, type: ${typeof text}`);// value: 4, type: number
자바 스크립트는 타입이 런타임 환경에서 결정되기 때문에, 에러가 많이 발생한다. 그래서 TypeScript 가 나오게 되었다. (자바 스크립트에 타입이 올려진 언어)
참고 : TypeScript는 결국 브라우저가 이해할 수 있는 자바스크립트로 변환을 위해 트랜스 컴파일러(BABEL 등)를 이용해야 함
Object
const dylan = {name:'dylan', age:20}; dylan.age = 21;
dylan 객체는 const 키워드로 선언되었기 때문에 한번 할당된 오브젝트는 다시 다른 오브젝트로 변경이 불가능하다. (즉, dylan이 가리키고 있는 메모리 주소에 있는 객체 자체는 변경이 불가능) 그러나 그 객체 안에 name, age 와 같은 변수들은 값을 재할당하는 것이 가능하다.
타입별 메모리 사이즈
자바스크립트는 미세한 메모리 컨트롤이 불가능하다.
- boolean 타입 : True 혹은 False 중 하나의 값만을 가지게 되므로 단 , 1 bit만을 차지한다.
- Number 타입 : ECMAScript 표준에 따르면, 숫자의 자료형은 정수, 소수 상관없이 무조건 64Bit(8byte)을 할당받게 된다. 자바스크립트에서는 정수, 소수 등에 대한 특별한 자료형이 없기 때문이다.
- String 타입 : 자바스크립트에서는 String 타입은 한 문자 당 16Bit를 할당받는다. 그러나 문자열은 한번 메모리가 할당되면 해제되기 전까지 변경이 불가능하다
추가 공부 필요
- 자바스크립트 메모리 해제 방안
- 가비지 콜렉터