너무너무 멋져 눈이눈이 부셔
[JS] 자바스크립트 문법 - 기초 문법과 변수 feat deep dive 본문
자바스크립트 기초 문법
자바스크립트는 세미콜론으로 문장을 구분한다.
대부분의 경우에는 문제 없이 동작하지만,
alert("에러가 발생합니다.")
[1, 2].forEach(alert)
//이것과 동일
alert("에러가 발생합니다.")[1, 2].forEach(alert)
이런 경우에서는 alert으로 1,2가 출력되지 않는다.(정상작동 시 1이라는 창이 뜨고 2라는 창이 떠야 한다)
자바스크립트가 대괄호 앞에서는 세미콜론이 있다고 가정하지 않기 때문.
그래서 줄바꿈으로 문을 나눴더라도 세미콜론을 넣는 것을 권장한다.
주석
// 이것이 주석
/*
여러줄 주석 (단축키 컨트롤 +쒸쁘뜨 + / )
*/
/*...*/안에 또 다른 /*...*/이 있을 수 없습니다.
자바스크립트 엄격모드
- 자바스크립튼는 업데이트 되면서 기존 기능을 없애는 게 아니라, 새로운 기능을 추가하는 식으로 업데이트 됨
- 그러나, ES5기준으로 기존 기능이 변경되는 것이 생김 -> 호환성 문제 발생!
- 변경사항 대부분은 ES5 기본에서 활성화 되지 않도록 설계 되었는데, use strict라는 지시자를 사용하면 변경사항이 활성화 된다.
use strict
// 최상단에 위치하면 스크립트 전체가 모던한 방식으로 동작.
// 함수 앞에 오면 해당 함수만 엄격모드로 실행.
- 자바스크립트 엔진을 이전 방식으로 되돌리는 지시자는 없음. 엄격 모드가 적용되면 돌이킬 방법은 없다.
자바스크립트 문법 - 변수
변수
변수는 위치(메모리 상 주소)를 기억하는 저장소이다. 즉, 변수란 메모리 주소에 접근하기 위해 사람이 이해할 수 있는 언어로 지정한 식별자라고 할 수 있다.
메모리에 값을 저장하기 위해서는 먼저 메모리 공간에 확보해야 할 메모리 크기(byte)를 알아내야 한다. 데이터 타입에 따라 메모리의 크기가 다르다.
- 할당 연산자 =를 사용해서 변수 안에 데이터를 저장한다.
let message = 'hello';
이 예제는 message라는 변수에 문자열 리터럴 'hello'를 값으로 할당하였다.
이렇게 'hello'라는 값을 캐싱해서, 다시 사용할 수 있도록 한다.
또한, 변수를 사용하면 값의 의미가 명확해져서 코드의 가독성이 좋아진다.
용어의미
용어 | 의미 |
데이터 타입(Data Type) | 프로그래밍 언어에서 사용할 수 있는 값의 종류 |
변수(Variable) | 값이 저장된 메모리 공간의 주소를 가리키는 식별자(identifier) |
리터럴(literal) | 소스코드 안에서 직접 만들어 낸 상수 값 자체를 말하며 값을 구성하는 최소 단위 |
값 | 프로그램에 의해 조작될 수 있는 대상 |
할당 | 변수에 값을 저장하는 것 |
참조 | 변수에 저장된 값을 읽는 것 |
식별자
메모리 주소에 붙인 이름.
myNumber은 값 23이 저장되어있는 메모리 Address를 기억한다.
이와 같이 식별자는 값이 아니라 메모리 주소를 기억하고 있다.
식별자로 값을 구별해서 식별한다는 것 = 식별자가 기억하고 있는 메모리 주소를 통해 메모리 공간에 저장된 값에 접근할 수 있다는 것을 의미
- 변수, 함수, 클래스 등의 이름은 모두 식별자이다. (자바스크립트에서 함수도 값이다)
- 메모리 상에 존재하는 어떤 값을 식별할 수 있는 이름은 모두 식별자
변수 선언
- 값을 저장하기 위한 메모리 공간 확보, 변수 이름과 확보된 메모리 공간의 주소를 연결해서 값을 저장할 수 있게 준비하는 과정.
- 변수를 사용하려면 반드시 선언이 필요하다.
- var, let, const 키워드가 있다.
- 한 줄에 여러 변수 선언도 가능 let user = 'me', user2 = 'you', user3 = 'we'; -> 가독성 떨어져서 권장하지는 않는다
//이런 방식도 가능
let user = 'John',
age = 25,
message = 'Hello';
- var/ let : 선언 후에 값을 재할당 할 수 있다
- const : 선언 후에 값을 재할당 할 수 없다(상수)
하지만! (이후 구체적으로 다룸)
- var는 블록스코프가 없어 (함수 스코프이거나 전역스코프) 블록 밖에서 접근이 가능함
- 중복 선언이 가능(두번째 선언 문은 무시됨)
선언과 할당
선언 : 변수를 선언하는 것.
할당 : 값을 저장하는 과정.
let name; //이상태에서 출력하면 undefinde로 암묵적 할당됨
name = 'kim'
const name ; // 값 선언과 할당이 동시에 이뤄져야 함.
Garbage value : undefined로 초기화하는 초기화 단계를 거치지 않으면 확보된 메모리 공간에는 이전에 다른 App이 사용했던 값이 남아있을 수 있다. 이 값을 쓰레기 값이라고 한다.
Excute Context(실행 컨텍스트) : 변수 이름을 비롯한 모든 식별자는 '실행 컨텍스트'에 등록된다.
- 실행 컨텍스트는 JS엔진이 소스코드를 평가하고 실행하기 위해 필요한 환경을 제공하고, 코드의 실행 결과를 실제로 관리하는 영역.
- JS 엔진은 실행 컨텍스트를 통해 식별자와 스코프를 관리한다.
참고!
변수 뿐만 아니라 모든 식별자를 사용하려면 선언이 필요하다
- 선언하지 않은 식별자를 참조하면 ReferenceError: 000 is not defined 에러가 발생한다.
호이스팅
호이스팅 : 모든 변수 선언문이 코드의 최상단으로 이동되는 것처럼 느껴지는 현상.(실제 이동되는 것은 아님!)
console.log(name);
var name = 'kim';
console.log(name);
//undefined
//'kim'
이는 마치 아래와 비슷한 느낌을 줌
var name; //선언만 상단에 함
console.log(name)
name ='kim'
console.log(name)
선언하기 전에 변수를 참조했는데도 불구하고, 에러가 아닌 "undefined"가 출력되는 현상, 기대와 다른 결과값을 볼 수 있다.
왜 이런가요?
변수 선언(선언 단계 & 초기화 단계)"이 소스코드가 한 줄씩 순차적으로 실행되는 시점, 즉 런타임(Runtime)이 아니라 그 이전 단계에서 먼저 실행되기 때문
JS 엔진이 변수 선언이 소스코드의 어디에 있든 상관없이 다른 코드보다 가장 먼저 실행한다.
- JS 엔진은 소스코드를 한 줄씩 실행하기에 앞서, 소스코드의 평가 과정을 거치면서 소스 코드 실행을 위한 준비를 한다
- JS 엔진은 변수 선언을 포함한 모든 선언문을 먼저 실행한다.
- 소스 코드 평가 과정이 끝나면, 변수 선언을 포함한 모든 선언문을 제외하고 소스 코드를 한 줄씩 실행한다.
var message = 'hello';
이런 한 문장도 실행 시점이 다르다
- 선언 : 런타임 이전 소스코드 평가 과정에서 먼저 실행
- 할당 : 런타임에 실행(위에서 부터 차례차례)
모든 선언문은 호이스팅 된다.
변수는 1. 선언단계, 2.초기화단계, 3.할당 단계로 생성되고, 2단계로 선언된다.
1. 선언단계 : 변수 객체에 변수를 등록한다.
2. 초기화단계 : undefined로 초기화
- var,키워드를 사용한 변수 선언은 선언단계와 초기화 단계가 동시에 진행 된다.
- 따라서, var 키워드로 선언한 변수는 어떠한 값도 할당하지 않아도 기본적으로 undefined 라는 값을 갖는다.
let과 const(모든 선언문)도 호이스팅이 된다
//let을 사용할 경우
console.log(name);
let name = 'kim';
// ReferenceError : Cannot access 'name' before initialization 발생
>> 어 뭐야 호이스팅이 안 발생하는데요?
그럼 이 경우를 보자
console.log(name)
//ReferenceError: name is not defined
name이 정의되지 않았다는 다른 문구의 에러 발생.
즉, 위에서 발생하는 에러는 일단 name이 선언은 되었다는 것. 다만 let을 사용해서 호이스팅으로 발생하는 접근을 막는다.
let(const) 키워드가 호이스팅 시 에러를 발생하는 이유
var와 let은 생명주기가 다르다. 특히, TDZ(일시적 사각지대: 선언~초기화 전 단계)를 주목하자.
호이스팅으로 선언이 끌어올려지는 듯하지만,
선언을 통해 메모리에는 있으면서 아직 초기화가 되지 않아 에러 발생.
즉 ES6로 넘어오면서 var를 쓰지 않는 이유는 다음과 같다.
1. 함수 레벨 스코프(유효 범위) : {}안에 써도 외부에서 참조할 수 있다. 전역변수 남발 (이후 설명)
2. var 키워드 생략 허용
3. 중복 선언 허용 : 의도치 않은 변수값 변경
4. 변수 호이스팅 : 번수 선언 전 참조 가능
----------------> side Effect (부수 효과)가 발생할 수 있어서 의도치 않게 코드가 동작한다!
함수 레벨 스코프(Function-level scope)함수 내에서 선언된 변수는 함수 내에서만 유효하며 함수 외부에서는 참조할 수 없다. 즉, 함수 내부에서 선언한 변수는 지역 변수이며 함수 외부에서 선언한 변수는 모두 전역 변수이다.
블록 레벨 스코프(Block-level scope)코드 블록 내에서 선언된 변수는 코드 블록 내에서만 유효하며 코드 블록 외부에서는 참조할 수 없다. (let, const)
값의 재할당
현재 변수에 저장된 값을 버리고 새로운 값을 저장하는 것.
var 키워드는 선언과 동시에 undefined로 초기화 되므로, 변수에 처음 할당하는 것도 재할당이다.
이름 컨벤션(규칙)
1) 카멜 케이스 : camelCase (변수나 함수)
2) 스네이크 케이스 : snake_case
3) 파스칼 케이스 : PascalCase (생성자 함수, 클래스 이름)
참고
https://github.com/youngminss/Docs-modernJS__deepDive/tree/master/01-Variable
'멋있는 JavaScript' 카테고리의 다른 글
[JS] 자바스크립트 연산자 (0) | 2024.03.28 |
---|---|
[JS] 자바스크립트 데이터 타입(자료형) (0) | 2024.03.28 |
[JS] 백준 16967 배열 복원하기 자바스크립트 node.js 풀이 (0) | 2024.03.28 |
[JS] 백준 1874 스택 수열 node.js 자바스크립트 풀이 (0) | 2024.03.19 |
자바스크립트 동작 원리 (1) | 2024.03.15 |