Developer_hong

ES5, ES6, 호이스팅(hoisting) 본문

프로그래밍/Java.Script

ES5, ES6, 호이스팅(hoisting)

Developer_hong 2022. 5. 28. 18:14
반응형

ES는 ECMASCRIPT를 말하며 JS 규격, 표준을 의미합니다

 

ES5 (2009년 출시)

ES6 (2015년 출시)

ES출시에 따른 차이로 인해 많은 문법들이 달라졌으며, 현업에서는 ES6+ 이상을 원하고 있는 추세이다

-> ES6를 알아야 ES5 레거시 코드를 리팩토링 할 수 있는 자질이 있다고 판단

 

ES5와 ES6 변화

- ES5에서 ES6로의 가장 큰 변화로는 let, const 변수가 추가됐으며 동작에서 차이가 있다

- Arrow function 추가됨

//ES5
function add (x,y){
    return x + y;
}
//ES6
fucntion add = (x,y) => x + y;

- Default prarmeter  추가됨

var test = function(x, y){
    var x = x || 1;
    var y = y || 2;
    return x + y;
}

const test = function (x = 1, y = 2){
    return x +y;
}

- Teplate literal 추가됨
ES6 이전 버전에서는 문자열 관리가 어려웠습니다
` (backtick) 사용 가능해지면서 개선됨

//ES5
var x = 'x';
var y = 'y';
var z = 'hello world' + x + ' ' + y +'입니다' + ' .';
console.log(z);

//ES6
var x = 'x';
var y = 'y';
const z = `hello world ${x} ${y} 입니다 .`;
console.log(z);

- Multi-line String
문자열 줄 바꿈하려면 \n을 이용해야 했으나
` (backtick) 사용 가능해지면서 개선됨

//ES5
var x = 'hello world \n' + 'JavaScript\n';

//ES6
const x =
`hello world
JavaScript\n`;

-class (클래스 추가)

JavaScript는 프로토 타입 기반의 객체지향 프로그래밍이지만 추가됨

 

-모듈 코드

재사용을 위한 조각을 뜻하는 모듈에서 세부사항은 캡슐화 시키고, API부분만 외부에 노출시킨다

<script type="module" scr="test1.mjs"></script>

 

type="module"을 사용하여 파일 확장자를 mjs로 변경시킨다

모듈은 모듈 스코프를 가지며 export, import 키워드를 사용합니다

 

- 디스트럭처링
비구조화를 뜻하는 단어로 객체나 배열에서 개별 변수에 할당하는 것을 말한다.

//Array 디스트럭처링
const test = [1, 2, 3];
const [x, y, z ] = test;

//Object 디스트러거링
const test = { x : 'hello', y : 'world' };
const { x, y} = test;


- 프로미스
비동기 통신에서 기존에는 콜백 함수를 사용한 콜백 패턴을 사용했고, 이는 콜백 헬을 만들었습니다
그래서 프로미스가 도입되었고, 프로미스 후속처리 메소드를 이용하여 에러 처리가 가능합니다

 

- String 메소드 추가됨 (includes, startWith, endWith)
문자열 메소드가 추가되어 로직 검사가 가능합니다


var 특징

1. 일반적으로 var 선언은 중복 선언이 가능하다

암묵적 결합이라고 부르는 이것은 협업 또는 프로잭트 진행에서 큰 지장을 초래할 수 있다

예를 들어 var start_time = 10; 으로 선언했는데,

include된 파일에서 var start_time=30;으로 선언된다면? start_time은 30으로 선언되며 상상하기 싫은 상황이 벌어집니다

 

2. var 생략 가능

Javascript

start_time = 10;

var start_time =10;

최근 TypeScript, Kotlin, Swift 등 여러 프로그래밍 언어에서 변수 Type형을 선언하는 것을 굉장히 중요시 한다

 

3. 변수 호이스팅

더보기

 호이스팅 (hoisting)

JavaScript에서 호이스팅(hoisting)이란, 인터프리터가 변수와 함수의 메모리 공간을 선언 전에 미리 할당하는 것을 의미합니다. var로 선언한 변수의 경우 호이스팅 시 undefined로 변수를 초기화합니다. 반면 let과 const로 선언한 변수의 경우 호이스팅 시 변수를 초기화하지 않습니다.

// 예제 1
// y만 호이스팅 대상

x = 1; // x 초기화. 그러나 명령문에 var가 없으므로 호이스팅이 발생하지 않음
console.log(x + " " + y); // 출력 결과 '1 undefined'
// JavaScript는 선언만 호이스팅하므로, 윗줄의 y는 undefined
var y = 2; // y를 선언하고 초기화

// 예제 2
// 호이스팅은 없지만, 변수 초기화는 (아직 하지 않은 경우) 변수 선언까지 병행하므로 변수를 사용할 수 있음

a = '크랜'; // a 초기화
b = '베리'; // b 초기화

console.log(a + "" + b); // 출력 결과'크랜베리'

- (출처 MDN https://developer.mozilla.org/ko/docs/Glossary/Hoisting)

console.log(start_time);

var start_time = 10;

출력하면 undefined 가 나온다

호이스팅에서 모든 변수들을 최상단으로 끌어올려서 초기화한다고 이해하면 편하다

 

4. 함수레벨 스코프

스코프(Scope)는  유효범위라는 의미를 가지는 단어로, 자바스크립트를 포함한 대부분의 언어에서 사용되는 개념입니다

 

- 함수 레벨 스코프(Function-level Scope)
함수 내에서 선언된 변수는 함수 내에서만 유효하며 함수 외부에서는 참조할 수 없다

함수 내부에서 선언한 변수는 지역 변수이며 함수 외부에서 선언한 변수는 모두 전역 변수이다.

- 블록 레벨 스코프(Block-level Scope)
코드 블록(function 함수, if문, for문, while문, try/catch문 등)내에서 선언된 변수는 코드 블록 내에서만 유효하며 코드 블록 외부에서는 참조할 수 없다. 즉, 코드 블록 내부에서 선언한 변수는 지역 변수이다.

var start_time = 10; //전역에 선언된 변수 start_time은 어디에든 참조할 수 있다

function test() {
  var start_time = 'define'; //함수 test내에서 선언된 변수 start_time은 함수 내부에서만 참조할 수 있고 함수 외부에서는 참조할 수 없다.
  console.log(start_time);
}

test(); // 'define' 출력
console.log(start_time); // 10 출력

그래서 var의 함수레벨 스코프 문제점은?

(function(){
    var ture=false;
    if(true) {
        var start_time = 10;
    }
    console.log(start_time); //if문에 해당하지 않는데 star_time 변수를 참조하여 10 출력
})();

따라서 결론적으로 var을 사용하게 되면

전역 변수로 선언되어 프로그램 실행 처음부터 끝 까지 메모리에 할당되며

include하거나 다른 js 파일을 불렀을 때 중복선언 또는 변수명이 공유되어 에러 가능성이 있고

스코프 체인의 문제도 생길 수 있습니다


let 또는 const를 통해서 해결
1. 블록레벨 스코프
2. 중복 선언 금지
3. 호이스팅 동작하지 않는 것처럼 동작
4. let은 변경가능하고, const는 변경 또는 재할당 불가능

//블록레벨 스코프
{
    let start_time = 10;
    console.log(start_time);
}

//중복 선언시 Uncaught SyntaxError: Identifier 'start_time' has already been declared 출력
{
    let start_time = 10;
    let start_time = 30;
    console.log(start_time);
}

//호이스팅 Uncaught ReferenceError: start_time is not defined 출력
{
    console.log(start_time);
    let start_time = 10;
}

//let, const 특징
//1.
let test_time_1 = 10;
test_time_1 = 30;

//2.
const test_time_2 = 10;
test_time_2 = 30; //Uncaught TypeError: Assignment to constant variable 출력

//3.
let test_time = {
    foo : 'foo',
};
test_time = {
    val : 'val',
};
test_time; //{val: 'val'}

//4.

const test_time = {
    foo : 'foo',
};
test_time = {
    val : 'val',
};
test_time; //Uncaught SyntaxError: Identifier 'test_time' has already been declared 출력

ES6에서는 var을 사용하지 않고, let const를 사용합니다
대부분 const를 사용하고 꼭 변경이 필요한 변수에만 let 사용하는 것을 권장합니다
let으로 선언한 변수는 호이스팅을 방생하지 않는 것 처럼 동작하며
let으로 선언한 변수는 선언 단계와 초기화 단계가 분리되어 런타임 이전에 JS 엔진에서 암묵적으로 선언 단계가 먼저 실행되기는 하나, 초기화 단계는 변수 선언문에 도달했을 때 실행됩니다.
(만약 초기화 단계가 실행되기 전 변수에 접근하려고 하면 참조에러 Uncaught ReferenceError 발생)

반응형