4장 변수
변수
- 변수 단계
- 선언단계: 변수 이름을 등록
- 초기화 단계: 값을 저장하기 위한 메모리 공간을 확보하고 undefined를 할당해서 초기화
*변수이름은 실행 컨텍스트 내에 키/값 형식인 객체로 등록되어 관리된다.
- 변수 선언은 런타임이 아니라 그 이전 단계에 서 먼저 실행된다.
: 소스코드를 한 줄씩 실행하기 전에 소스코드 실행을 위한 준비 단계인 소스 코드 평가 단계에서 변수 선언을 포함한 모든 선언문을 소스코드에서 찾아내 먼저 실행한다.
이렇게 소스코드가 실행되는 런타임 이전 단계에서 먼저 실행되면서 변수 선언문이 코드 선두로 끌어 올려진 것처럼 동작하는 것이 변수 호이스팅이다.
>>var score 가 호이스팅되어 먼저 선언되기 때문에 소스코드가 런타임에서 실행되면서 score=80을 만나면 할당이 되어 정상적으로 이후 콘솔에 출력될 것이다.
변수를 할당/재할당할 때마다 메모리 주소가 바뀌는 것! 이전 메모리 주소에서 공간을 지우고 그 공간에 재할당하는 것이 아니다.
5장 표현식과 문
5장 표현식과 문
값
: 값은 표현식이 평가되어 생성된 결과
리터럴
:사람이 이해할 수 있는 문자 또는 약속된 기호를 사용해 값을 생성하는 표기법
표현식
: 값으로 평가될 수 있는 문
=값으로 평가될 수 있는 문은 모두 표현식이다.
문
: 프로그램을 구성하는 기본 단위이자 최소 실행 단위
→ 토큰 : 문법적으로 더 이상 나눌 수 없는 코드의 기본 요소(키워드, 식별자, 연산자, 세미클론…)
표현식인 문과 표현식이 아닌 문
:표현식인 문은 값으로 평가될 수 있는 문, 표현식이 아닌 문은 값으로 평가될 수 없는 문
→ 가장 간단한 방법은 변수에 할당해 보는 것!
변수 선언문은 변수에 할당할 수 없기 때문에 표현식이 아니다.
할당문은 변수에 할당할 수 있으므로 표현식이다.
6장 데이터 타입
6장 데이터 타입
숫자타입
:자바스크립트에서는 모든 수를 실수로 처리
문자열 타입
:따움표로 값을 감싼다.
템플릿 리터럴
:백틱을 사용
템플릿 리터럴 사용 시 줄바꿈과 공백이 허용된다.
${} ←이걸 통해서 표현식을 감싸서 템플릿 리터럴 내에 삽입할 수 있다.
이 때 표현식의 평가 결과가 문자열이 아니더라도 문자열로 타입이 강제로 변환된다.
undefined
: 개발자가 의도적으로 할당하기 위한 값이 아니라 자바스크립트 엔진이 변수를 초기화 할 때 사용하는 값
따라서 개발자가 의도적으로 undefined를 할당하는 것은 목적에 맞지 않으므로 권장하지 않는다. 그럴 경우 null을 사용하는 것을 권장
null
:변수에 값이 없다는 것을 의도적으로 명시할 때 사용
심벌 타입
:변경 불가능한 원시 타입
다른 값과 중복되지 않는 유일무이한 값이다.
객체 타입
:11장에서 설명
데이터 타입에 따른 메모리 공간의 확보와 참조
-데이터 타입에 대한 이해가 중요한 이유는 자바스크립트는 데이터 타입, 값의 종류에 따라 정해진 크기의 메모리를 확보하기 때문이다.
위와 같은 예제에서 자바스크립트는 리터럴 100을 숫자타입으로 해석 → 숫자 타입의 100을 저장하기 위해 8바이트의 메모리 공간 확보 → 100을 2진수로 저장
이러한 과정을 거치게 된다.
그리고 이러한 값을 다시 참조하는 경우 변수에 숫자 타입의 값이 할당되어 있으므로 자바스크립트는 score 변수를 숫자 타입으로 인식하고 8바이트 단위로 메모리 공간에 저장된 값을 읽어 들인다.
그리고 변수가 숫자 타입으로 인식되기 때문에 읽어들인 2진수를 숫자로 해석한다.
즉 데이터 타입이 필요한 이유는
- 값을 저장할 때 메모리 공간의 크기를 결정하기 위해
- 값을 참조할 때 한번에 읽어들여야 할 메모리 공간의 크기를 결정하기 위해
- 메모리에서 읽어 들인 2진수를 어떻게 해석할지 결정하기 위해
정적타입언어와 동적타입언어
c언어 자바 등은 변수를 선언할 때 변수에 할당할 값의 타입을 선언해야 한다.
이를 명시적 타입선언이라 하며 컴파일 시점에서 할당된 값이 선언된 타입과 같은지 타입체크가 일어나기 때문에 안정적인 코드를 구현할 수 있다.
하지만 자바스크립트는 let, var, const로 변수를 선언할 뿐 타입을 같이 선언하지 않는다. 자바스크립트는 변수 선언이 아닌 변수가 할당될 때 타입이 결정되는 동적타입언어이기 때문이다.
이러한 동적타입언어는 개발자가 예상하지 못한 동작이 일어날 수 있기 때문에 유연성은 높으나 신뢰성은 떨어진다.
7장 연산자
연산자
산술 연산자
:피연산자를 대상으로 수학적 계산을 수행해 새로운 숫자 값을 만든다.
- 증감연산자
++1, —1 :전위 증가/감소 연산자
1++, 1—:후위 증가/감소 연산자
비교 연산자
-동등 비교 연산자는 좌항과 우항의 피연산자를 비교할 때 암묵적 타입 변환을 통해 타입을 일치시킨 후 같은 값인지 비교
-일치 비교 연산자는 타입변환이 일어나지 않고 타입과 값이 모두 같은 경우에만 true를 반환한다.
typeof 연산자
-null타입은 typeof 연산자로 사용하면 object가 나온다. 따라서 null은 일치 연산자를 사용해야 한다.
대부분의 연산자는 다른 코드에 영향을 주지 않는다.
1+2의 경우 새로운 2라는 값을 생성할 뿐이지 다른 코드에 영향을 주는 것은 아니다.
하지만 이러한 부수효과를 주는 연산자가 있는데
할당 연산자(=), 증가/감소 연산자(++/—), delete 연산자
이다.8장 제어문
제어문은 위에서 아래 방향으로 실행되는 코드의 실행 흐름을 인위적으로 제어
블록문
: 0개 이상의 문을 중괄호로 묶은 것 (=코드블록, 블록)
조건문
:주어진 조건식의 평가 결과에 따라 코드블록의 실행을 결정
- if…else 문
-만약 조건식이 불리언 값이 아닌 값으로 평가되면 암묵적으로 불리언 값으로 강제 변환되어 실행할 코드 블록을 결정한다.
- switch 문
-만약 case문 실행 후에 break를 걸지 않으면 모든 case문과 default 문이 실행되는데 이를 폴스루라고 한다.
따라서 원하는 값을 할당하기 위해서는 case문마다 break를 걸어주어야 한다.
폴스루가 유용한 경우도 있다.
다음은 윤년을 계산하는 예이다.
반복문
: 조건식의 평가 결과가 참인 경우 코드블록을 실행, 조건문이 거짓일 때까지 반복
- for문 :반복 횟수가 명확할 때
- while 문: 반복 횟수가 불명확할 때
- do…while문 : 코드 블록을 먼저 실행하고 조건식을 평가. 코드블록은 무조건 한 번 이상 실행된다.
9장 타입변환과 단축평가
타입 변환은 크게 개발자가 의도적으로 값의 타입을 변환하는 명시적 타입 변환과 자바스크립트 엔진에 의해 암묵적으로 타입을 변환하는 암묵적 타입 변환이 있다.
암묵적 타입 변환
: 코드의 문맥에 부합하지 않을 때 자바스크립트는 에러를 띄우는 것이 아니라 암묵적 타입 변환을 통해 표현식을 평가한다.
- 문자열 타입으로 변환
이항 연산자 +를 사용할 때 피연산자 중 하나 이상이 문자열이면 문자열 연결 연산자로 동작하여 다른 하나도 문자열로 변환된다.
→ 문자열 연결 연산자의 역할은 문자열 값을 만드는 것이기 때문!
- 숫자 타입으로 변환
: 산술 연산자 -, * / 등을 사용할 경우 모든 피연산자는 숫자 타입으로 변환된다.
→ 산술 연산자의 역할은 숫자 값을 만드는 것이기 때문이다!
하지만 피연산자를 숫자 타입으로 변환할 수 없는 경우 평과 결과는 NaN이 된다.
: 단항 연산자 +는 피연산자가 숫자타입이 아닌 경우 숫자 타입으로 변환하기 때문에 타입 변환이 필요할 때 유용하게 사용할 수 있다.
: 산술 연산자와 마찬가지로 비교 연산자 역시 모든 피연산자는 숫자 타입으로 변환된다.
하지만 비교 연산자 중에서 동등 비교 연산자(==)는 암묵적 타입 변환을 통해 타입을 일치시킨 후 값을 비교하지만 일치 비교 연산자(===) 의 경우 타입 변환이 일어나지 않는다.
*이러한 동등 비교 연산자가 편리할 때도 있지만 예기치 않은 결과를 만들어내기도 하므로 일치 비교 연산자를 사용하는 것이 좋다.
명시적 타입 변환
: 개발자가 의도에 따라 명시적으로 타입을 변경하는 방법
- 문자열 타입으로 변환
- String 생성자 함수를 new 연산자 없이 호출
- toString() 메서드를 사용하는 방법
- 문자열 연결 연산자를 이용하는 방법
- 숫자 타입으로 변환
- Number생성자 함수를 new 연산자 없이 호출
- parseInt. parseFloat 함수를 사용하는 방법(문자열만 가능)
- +단항연산자 이용
- *산술연산자 이용
- 불리언 타입으로 변환
- Boolean 생성자 함수를 new 연산자 없이 호출
- ! 부정 논리 연산자를 두 번 사용하는 방법
단축평가
- 논리 연산자를 사용한 단축 평가
: 논리곱 연사자(&&)는 두 개의 피연산자가 모두 true일 때 true를 반환
두 개의 피연산자를 모두 평가해야하므로 두번째 피연산자가 평가결과를 결정
→ 논리곱 연산자는 값이 true 일 때 논리 연산의 결과를 결정하는 두 번째 피연산자를 반환한다.
:논리합 연산자(||)는 두 개의 피연산자 중 하나만 true로 평가되어도 true를 반환한다.
하나만 true여도 true이므로 첫번째 피연산자가 평가 결과를 결정
→ 논리합 연산자는 논리 연산의 결과를 결정하는 첫 번째 피연산자를 반환
- 어떤 조건이 true일 때, 논리곱 연산자는 if문을 대체할 수 있다.
- 어떤 조건이 false일 때, 논리합 연산자로 if문을 대체할 수 있다.
옵셔널 체이닝 연산자
?. 는 좌항의 피연산자가 null이거나 undefined인 경우 undefined를 반환하고 그렇지 않으면 우항의 프로퍼티 참조를 이어간다.
옵셔널 체이닝 연산자가 도입되기 이전에는 논리 연산자를 사용했는데 논리연산자와 옵셔널 체이닝 연산자의 차이점은 좌항 피연산자가 false로 평가될 때이다.
논리연산자의 경우 좌항 피연산자가 false로 평가되면 좌항 피연산자를 그대로 반환한다.
옵셔널 체이닝 연산자는 좌항 피연산자가 false여도 null이나 undeifined가 아니면 우항의 프로퍼티 참조를 이어간다.
null 병합 연산자
null 병합 연산자 ??는 좌항의 피연산자가 null 또는 undefined인 경우 우항의 피연산자를 반환, 그렇지 않으면 좌항의 피연산자를 반환한다.
그래서 이러한 null 병합 연산자는 이렇게 변수의 기본값을 설정할 때 유용하다.
null 병합 연산자가 도입되기 이전에는 논리합연산자를 이용했는데 이 둘의 차이점도 좌항의 피연산자가 false일 때 있다.
논리합 연산자의 경우 좌항의 피연산자가 false이면 우항의 피연사자가 반환된다. 이때 만약 변수에 falsy값인 0이나 ””을 넣고싶은 경우 예기치 않은 동작이 발생할 수 있다.
하지만 null 병합 연산자의 경우 좌항의 피연산자가 false여도 null이나 undeifined가 아니면 좌항의 피연산자를 반환한다.
10장 객체 리터럴
객체란?
:원시 값을 제외한 나머지 값(함수, 배열, 정규 표현식 등)은 모두 객체이다.
- 원시 타입: 단 하나의 값. 변경 불가능
- 객체 타입: 다양한 타입의 값을 하나의 단위로 구성한 복합적인 자료구조. 변경 가능
자바스크립트에서 사용하는 모든 값은 프로퍼티의 값이 될 수 있다. 함수 역시 일급 객체이므로 값으로 취급할 수 있다. 만약 프로퍼티 값이 함수인 경우 일반 함수와의 구분을 위해 메서드라고 부른다.
생성방법
- C++이나 자바같은 클래스 기반 객체지향 언어는 클래스를 사전에 정의하고 필요한 시점에 new 연산자와 함께 생성자를 호출하여 인스턴스를 생성하는 방식을 사용
- 자바스크립트는 프로토타입 기반 객체지향 언어로서 다양한 객체 생성 방법 지원
- 객체 리터럴 → { }
- Object 생성자 함수
- 생성자 함수
- Object.create 메서드
- 클래스
*객체 리터럴은 코드블록이 아닌 표현식이기 때문에 세미클론을 붙인다!
프로퍼티
객체는 프로퍼티의 집합, 프로퍼티는 키와 값으로 구성된다.
- 식별자네이밍규칙을 따르는 프로퍼티키의 경우 따움표를 붙이지 않아도 되지만 따르지 않는다면 따움표를 붙여야 한다.
- 프로퍼티 키에 문자열이나 심벌 값 외의 값을 사용하면 암묵적 타입 변환을 통해 문자열로 변환된다.
메서드
: 프로퍼티 값이 함수일 경우 일반 함수와 구분하기 위해 메서드라 부른다.
프로퍼티 접근
- 마침표를 사용하는 마침표 표기법
- 대괄호를 사용하는 대괄호 표기법
: 대괄호 표기법을 사용하는 경우 대괄호 표기법 내부의 프로퍼티 키는 반드시 따움표로 감싼 문자열이어야 한다.
:프로퍼티 키가 식별자 네이밍 규칙을 준수하지 않은 이름인 경우에도 반드시 대괄호 표기법을 사용해야 한다.
:키를 동적으로 생성하는 경우(계산, 변수 등) 대괄호 표기법을 사용해야 한다.
프로퍼티 축약 표현
- 값으로 사용한 변수 이름과 프로퍼티 키가 동일한 이름이면 프로퍼티 키를 생략할 수 있다.
11장 원시 값과 객체의 비교
- 원시 타입
: 변경 불가능
: 변수에 할당하면 변수에는 실제 값이 저장
: 다른 변수에 할당하면 원본의 원시 값이 복사되어 전달-값에 의한 전달
- 객체 타입
: 변경 가능한 값
: 변수에 할당하면 변수에는 참조 값이 저장
: 다른 변수에 할당하면 참조 값이 복사되어 전달 - 참조에 의한 전달
원시값
-변수는 하나의 값을 저장하기 위해 확보한 메모리 공간 그 자체, 또는 그 메모리 공간을 식별하기 위해 붙인 이름
-값은 변수에 저장된 데이터로서 표현식이 평가되어 생성된 결과
→ 변경 불가능하다는 것은 변수가 아니라 값에 대한 진술이다.
원시 값이 변경 불가능하다는 것은 원시 값 자체를 변경할 수 없다는 것이지 변수를 변경할 수 없는 것이 아니다. 변수는 언제든지 재할당을 통해서 변수 값을 변경(교체) 할 수 있다.
이미 생성된 문자열의 일부 문자를 변경해도 반영되지 않는다. 문자열은 변경 불가능한 원시 값이기 때문이다!
따라서 문자열은 변경할 수 없으나 변수에 새로운 문자열을 재할당하는 것은 가능하다.
- 값에 의한 전달
변수에 원시 값을 갖는 변수를 할당하면 원시 값이 복사되어 전달된다. 하지만 동일한 메모리 공간을 가리키는 것이 아니라 copy는 새로운 메모리 공간에 80을 저장하고 가리키는 것이다. 따라서 score과 copy는 복사 된 이후에 독립적으로 조작이 가능하다.
객체
: 객체를 할당한 변수가 기억하는 메모리 주소는 객체가 저장되어 있는 메모리 공간의 주소이다. 이 값을 참조 값이라 한다.
:객체는 변경 가능한 값이기 때문에 재할당 없이 객체를 직접 변경할 수 있다.
이런 방법으로 객체를 효율적으로 사용할 수 있지만 여러 개의 식별자가 하나의 객체를 공유할 수 있다는 단점이 있다.
이렇게 객체를 복사하는 경우 원본의 참조 값이 복사되어 전달된다. 이 말은 즉 객체 자체가 복사되는 것이 아니기 때문에 person과 copy는 같은 객체를 가리키게 되고 한쪽에서 프로퍼티를 변경하는 등의 로직이 일어나면 다른 한쪽에도 영향을 준다는 것이다.
12장 함수
함수란?
:일련의 과정을 문으로 구현하고 코드 블록으로 감싸서 하나의 실행 단위로 정의한 것
- 매개변수: 함수 내부로 입력을 전달받는 변수
- 인수: 입력
- 반환값: 출력
→ 함수를 사용할 경우 코드의 재사용성 측면에서 매우 유용하기 때문에 유지보수의 편의성을 높이고 실수를 줄여 코드의 신뢰성을 높이는 효과가 있다.
*함수는 객체이다!
함수 정의
- 함수 선언문
- 함수 표현식
- Fucntion 생성자 함수
- 화살표 함수(ES6)
함수선언문
함수 선언문은 표현식이 아닌 문이다.
표현식이 아닌 문의 경우 변수에 할당할 수 없는데 함수선언문은 변수에 할당이 가능하다 .이는 함수 선언문의 경우 표현식인 함수 리터럴과 형태가 동일하기 때문에(함수 이름을 생략할 수 없다는 점을 제외하면) 함수 선언문이 함수 리터럴로 해석될 수도 있다는 의미이다.
→ 코드 문맥에 따라 함수 리터럴 혹은 함수 선언문으로 해석된다.
함수 선언문과 함수리터럴의 차이는 호출할 수 있느냐 없느냐이다.
함수 리터럴의 경우 함수 이름은 함수 내부에서만 참조할 수 있는 식별자이다. 따라서 외부에서 함수를 가리키는 식별자가 없기 때문에 호출할 수 없는 것이다.
하지만 이는 함수 선언문도 마찬가지이다. 하지만 차이점이 있다면 함수 선언문인 경우 자바스크립트 엔진에서 생성된 함수를 호출하기 위해 함수 이름과 동일한 이름의 식별자를 암묵적으로 생성하고 거기에 함수 객체를 할당한다는 것이다.
그래서 함수는 함수 이름으로 호출하는 것이 아니라 함수 객체를 가리키는 식별자로 호출하는 것이다.
함수 생성 시점과 함수 호이스팅
함수 선언문
- 함수 선언문 이전에 호출할 수 있음.
→ 런타임이 전에 함수 객체가 먼저 생성되어 동일한 이름의 식별자를 암묵적으로 생성하고 생성된 함수 객체에 할당하기 때문 : 함수 호이스팅
함수 표현식
- 함수 표현식 이전에 호출할 수 없음.
→ 함수 표현식으로 함수를 정의하면 함수 호이스팅이 아니라 변수 호이스팅이 일어남
함수 호이스팅 vs 변수 호이스팅
변수 호이스팅은 런타임 이전에 식별자를 먼저 생성하지만 undefined로 초기화된다.
함수 호이스팅은 런타임 이전에 식별자를 생성하면서 암묵적으로 생성된 식별자로 함수객체를 초기화한다. 따라서 변수 호이스팅은 변수 선언문이 전에 변수를 참조하면 undefined가 뜨지만 함수 호이스팅은 함수 선언문 이전에 호출해도 호출이 가능하다.
화살표 함수
화살표 함수는 기존의 함수보다 표현뿐만 아니라 내부 동작도 간략화되어 있다.
- 기존 함수와 this 바인딩 방식 다름
- prototype프로퍼티 없음
- arguments 객체를 생성하지 않음
함수 호출
- 매개변수
: 매개변수의 개수와 인수의 개수가 일치하지 않아도 에러가 발생하지 않는다. 인수가 할당되지않은 매개변수 값은 undefined이다.
: 매개변수보다 인수가 더 많은 경우엔 무시된다.
참조에 의한 전달과 외부 상태의 변경
매개 변수는 함수 내부에서 변수로 작동하는데 이 역시 값에 의한 전달, 참조에 의한 전달 동일하게 적용된다.
원시타입의 경우 변경 불가능한 값이기 때문에 재할당을 통해 새로운 원시값으로 교체되어 원복이 훼손되지 않는다. 하지만 객체타입의 경우 변경 가능한 값이기 때문에 참조 값이 복사되어 원복이 훼손된다.
따라서 이러한 버그를 줄이기 위해 최대한 외부 상태에 의존하지 않는 순수함수를 작성해야 한다.
즉시 실행 함수(IIFE)
:익명 함수를 사용하는 것이 일반적, 다시 호출할 수 없다.
재귀 함수
:자기 자신을 호출하는 함수
:탈출 조건이 반드시 있어야한다! 탈출 조건이 없으면 무한 호출되어 스택 오버플로 에러가 발생
콜백 함수
:함수의 매개변수를 통해 다른 함수의 내부로 전달되는 함수
:매개 변수를 통해 함수의 외부에서 콜백 함수를 전달받은 함수를 고차함수라고 한다.
순수 함수와 비순수 함수
- 순수 함수
: 외부상태에 의존하지 않고 변경하지 않는 부수 효과가 없는 함수
:인자의 불변성을 유지
: 함수 내부상태에만 의존한다고 해도 내부 상태가 호출될 때마다 변화하는 값이라면 순수 함수가 아니다.
- 비순수 함수: 외부상태에 의존하거나 외부 상태를 변경하는 부수효과가 있는 함수
:부수효과란?
→ 함수가 수행해야 하는 본연의 일 이외의 부수적으로 수행하는 일
ex) 두 개의 인수를 전달받아 합계를 반환하는 함수, console.log, alert…
인수를 전달받지 않고 내부에서 외부 상태를 직접 참조하면 외부 상태의 의존하게 되고, 외부 상태도 변경할 수 있으므로 비순수함수이다.
매개변수를 통해 객체를 전달받아도 비순수 함수
13장 스코프
스코프란?
식별자가 유효한 범위
→ 모든 식별자는 자신이 선언된 위치에 의해 다른 코드가 식별자 자신을 참조할 수 있는 유효 범위가 결정된다.
스코프의 종류
- 전역: 코드의 가장 바깥 영역, 전역 스코프, 전역 변수
- 지역: 함수 몸체 내부, 지역 스코프, 지역 변수
→ 전역 스코프는 어디서든 참조할 수 있고 지역 변수는 자신의 지역 스코프와 하위 지역 스코프에서 유효하다.
- 스코프 체인: 스코프가 계층적으로 연결되어 있는 것
→ 변수를 참조할 때 스코프 체인을 통해 변수를 참조하려는 코드의 스코프에서 시작하여 상위 스코프 방향으로 이동하며 선언된 변수를 검색한다.
var는 함수레벨 스코프
:함수 코드블록만을 지역 스코프로 인정
렉시컬 스코프
위 예제의 실행결과는 bar함수의 상위 스코프가 무엇인지에 따라 결정
- 함수를 어디서 호출했는지에 따라 함수의 상위 스코프를 결정
- 함수를 어디서 정의했는지에 따라 함수의 상위 스코프를 결정
→ 1번 방식: 상위 스코프는 foo의 지역스코프와 전역스코프 :동적 스코프 (함수를 정의하는 시점에서는 함수가 어디서 호출될 지 알 수 없으므로 호출되는 시점에 동적으로 상위 스코프를 결정)
→ 2번 방식: 상위 스코프는 전역 스코프 : 렉시컬 스코프/정적 스코프 (함수 정의가 평가되는 시점에 상위 스코프가 정적으로 결정)
—> 대부분 렉시컬 스코프를 따른다.
14장 전역 변수의 문제점
지역 변수의 생명 주기
- 지역 변수의 생명주기는 함수의 생명주기와 일치한다.
전역 변수의 생명 주기
- var 키워드로 선언한 전역 변수는 전역 객체의 프로퍼티가 되어 전역 변수의 생명주기가 전역 객체의 생명주기와 일치
→ 전역객체 window의 프로퍼티가 되는 것
전역 변수의 문제점
- 암묵적 결함
: 모든 코드가 전역 변수를 참조하고 변경할 수 있는 것
→ 코드의 가독성이 나빠지고 의도치 않은 변경이 있을 수 있음
- 긴 생명 주기
: 전역 변수는 생명 주기가 길어서 메모리 리소스도 오랜 기간 소비
- 스코프 체인 상에서 종점에 존재
: 변수를 검색할 때 가장 마지막에 검색된다는 것
→ 전역 변수의 검색 속도가 가장 느리다.
- 네임스페이스 오염
: 자바스크립트의 문제점 중 하나는 파일이 분리되어 있어도 전역 변수를 공유한다는 점이다. 따라서 예상치 못한 결과가 나올 수 있다.
지역 변수로 사용할 수 있다면 지역 변수를 사용하자!
전역 변수 사용을 억제하는 방법
- 즉시실행함수
: 모든 코드를 즉시실행함수로 감싸면 모든 변수는 즉시 실행함수의 지역 변수가 된다.
- 네임스페이스 객체
:전역에 네임스페이스 역할을 담당할 객체를 생성하고 전역 변수처럼 사용하고 싶은 변수를 프로퍼티로 설정
- 모듈패턴
: 관련 있는 변수와 함수를 모아 즉시실행함수로 감싸 하나의 모듈을 만드는 것
→ 전역 변수 억제 및 캡슐화 구현 가능
- ES6 모듈
: ex6 모듈을 사용하면 전역변수를 사용할 수 없다. 파일 자체의 독자적인 모듈 스코프를 제공
15장 let, const 키워드와 블록 레벨 스코프
var 키워드로 선언한 변수의 문제점
- 변수의 중복 선언 허용
- 함수 레벨 스코프: 함수 외부에서 var로 선언한 변수는 모두 전역 변수
- 변수 호이스팅: 변수 선언문 이전에 참조할 수 있다. (undefined 반환)
let 키워드
- 변수 중복 선언 금지
- 블록 레벨 스코프: 모든 코드 블록을 지역 스코프로 인정
- 변수 호이스팅: 변수 선언문 이전에 참조하면 참조에러가 발생
→선언단계와 초기화 단계가 분리되어서 진행되기 때문이다. 초기화 단계는 변수 선언문에 도달했을 때 실행
→ 스코프의 시작 지점부터 초기화 시작 지점까지 변수를 참조할 수 없는 구간을 일시적 사각지대(TDZ)라고 부른다.
- 전역 객체와 let
→ let키워드로 선언한 전역 변수는 전역 객체의 프로퍼티가 아니다. let 전역 변수는 보이지 않는 개념적인 블록 내에 존재하게 된다.
const 키워드
- 선언과 초기화
:cosnt 키워드로 선언한 변수는 반드시 선언과 동시에 초기화해야 한다.
- 블록레벨 스코프
- 변수 호이스팅이 발생하지 않는 것처럼 동작
- 재할당 금지
- 상수
:const 키워드로 선언한 변수에 원시 값을 할당하는 경우 변수 값을 변경할 수 없다.
- const 키워드와 객체
: const 키워드로 선언된 변수에 객체를 할당하는 경우 값을 변경할 수 있다. 변경 가능한 값인 객체는 재할당 없이도 값을 직접 변경할 수 있기 때문이다.
→ const 재할당 금지를 의미하는 것이지 불변을 의미하는 것이 아니다.
퀴즈
Q1. 해당 결과를 적고 이유를 설명하시오.
Q2. 해당 결과를 적고 이유를 설명하시오.