Programming/javascript

자바스크립트 기초부터 모던 자바스크립트까지 - 기초편

KOOCCI 2022. 7. 2. 12:03

목표 : 자바스크립트의 가장 기초적인 내용부터 알아본다.


변수

하나의 값을 저장하기 위해 확보한 메모리 공간 자체 또는 그 메모리 공간을 식별하기 위해 붙인 이름

변수 선언

변수를 생성하는 것

값을 저장하기 위한 메모리 공간을 확보하고, 변수 이름과 확보된 메모리 공간의 주소를 연결하여 값을 저장할 수 있게 준비하는 것

변수를 사용하려면 반드시 선언이 필요하며, var, let, const 키워드를 사용한다.

  • 선언 단계
    • 변수 이름을 등록해서 자바스크립트 엔진에 변수의 존재를 알린다.
  • 초기화 단계
    • 값을 저장하기 위한 메모리 공간을 확보하고 암묵적으로 undefined를 할당해 초기화한다.

변수 선언의 실행 시점과 변수 호이스팅

console.log(score) // undefined
var score; // 변수 선언
  • 변수 선언이 소스코드가 한 줄씩 순차적으로 실행되는 시점, 즉 런타임이 아니라 그 이전 단계에서 먼저 실행된다.
  • 자바스크립트 엔진은 소스코드를 한 줄씩 실행하기 전에 먼저 소스코드의 평가, 실행 두 가지로 진행이 되며, 평가 과정에서 변수 선언을 포함한 모든 선언문(변수, 함수 등)을 소스코드의 어디에 있든 상관없이 먼저 실행한다.
  • 변수 선언(선언 + 초기화)이 소스코드가 순차적으로 실행되는 런타임 이전 단계에서 먼저 실행된다.
  • 변수 선언문이 코드의 선두로 끌어 올려진 것처럼 동작하는 자바스크립트 고유 특징변수 호이스팅이라고 한다.
  • 변수 뿐만이 아니라, var, let, const, function, function*, class 키워드를 사용해 선언하는 모든 식별자(변수, 함수, 클래스 등)은 호이스팅된다.

값의 할당 & 재할당

var score; // 선언
score = 80; // 할당

변수 선언은 소스코드가 순차적으로 실행되는 시점인 런타임 이전에 먼저 실행되지만, 할당은 소스코드가 순차적으로 실행되는 시점인 런타임에 실행된다.

var score = 80; // 변수 선언과 값의 할당
score = 90; // 재할당

var 키워드로 선언한 변수는 선언과 동시에 undefined로 초기화되기 때문에 엄밀히 말하면 변수에 처음 값을 할당하는 것도 재할당이다.

재할당변수에 저장된 값을 다른 값으로 변경한다. 그래서 변수라고 하며, 만약 값을 재할당할 수 없어서 변수에 저장된 값을 변경할 수 없다면 변수가 아니라 상수(constant)라 한다.

즉, 상수는 단 한번만 할당할 수 있는 변수다.

표현식과 문

식(표현식: expression)이 평가(evaluate)되어 생성된 결과

// 10 + 20은 평가되어 숫자 값 30을 생성한다.
10 + 20; // 30

리터럴

사람이 이해할 수 있는 문자 또는 약속된 기호를 사용해 값을 생성하는 표기법(notation)

자바스크립트 엔진은 코드가 실행되는 시점인 런타임에 리터럴을 평가해 값을 생성한다.

리터럴 예시 비고
정수 리터럴 100  
부동소수점 리터럴 10.5  
2진수 리터럴 0b0100001 0b로 시작
8진수 리터럴 0o101 ES6에서 도입, 0o로 시작
16진수 리터럴 0x41 ES6에서 도입, 0x로 시작
문자열 리터럴 'hello'
"hello"
 
불리언 리터럴 true
false
 
null 리터럴 null  
undefined 리터럴 undefined  
객체 리터럴 { name : 'Lee', address: 'Seoul' }  
배열 리터럴 [ 1, 2, 3]  
함수 리터럴 function() {}  
정규 표현식 리터럴 /[A-Z]+/g  

표현식

var score = 100;
var score = 50 + 50;
score; // 100

값으로 평가될 수 있는 문(statement)

표현식이 평가되면 새로운 값을 생성하거나 기존값을 참조한다.

리터럴 역시 값으로 평가되므로, 표현식 중 하나다.

프로그램을 구성하는 기본 단위이자 최소 실행 단위

문의 집합으로 이뤄진 것이 프로그램이며, 문을 작성하고 순서에 맞게 나열하는 것이 프로그래밍이다.

문은 여러 토큰으로 이루어진다.

토큰: 문법적인 의미를 가지며, 문법적으로 나눌 수 없는 코드의 기본 요소
키워드, 식별자, 연산자, 리터럴, 세미콜론이나 마침표 등 특수 기호는 문법적인 의미를 가지므로 모두 토큰이다. 문은 명령문이라고도 한다. , 컴퓨터에 내리는 명령이다.
선언문, 할당문, 조건문, 반복문 등으로 구분이 된다.

데이터 타입

데이터 타입 종류

구분 데이터 타입 설명
원시타입(primitive type) 숫자(number) 타입 숫자, 정수와 실수 구분없이 하나의 숫자 타입만 존재
문자열(string) 타입 문자열
불리언(boolean) 타입 논리적 참(true)과 거짓(false)
undefined 타입 var 키워드로 선언된 변수에 암묵적으로 할당되는 값
null 타입 값이 없다는 것을 의도적으로 명시할 때 사용하는 값
심벌 타입 ES6에서 추가된 7번째 타입
객체 타입 객체, 함수, 배열 등

개발자는 명확한 의도를 가지고 타입을 구별해서 값을 생성한다.

자바스크립트 엔진은 타입을 구별해서 값을 취급한다.

 

숫자 타입

자바스크립트는 정수, 실수를 구분하지 않고 하나의 숫자 타입을 갖는다.

ECMAScript 사양에 따르면, 64비트 부동소수점 형식 을 따른다.

, 모든 수를 실수로 처리하며, 정수만은 따로 취급하지 않는다.

console.log(1 === 1.0) // true

추가적으로 세 가지 특별한 값도 표현할 수 있다.

  • Infinity : 양의 무한대
  • -Infinity : 음의 무한대
  • NaN: 산술 연산 불가(Not a Number)

단, 자바스크립트는 대소문자를 구별하므로 NAN, Nan, nan은 하나의 식별자로 해석한다.

 

문자열 타입

텍스트 데이터를 나타낼 때 사용하고, 0개 이상의 16비트 유니코드 문자(UTF-16)의 집합으로 전 세계 대부분의 문자를 표현할 수 있다.

자바스크립트는 문자열은 원시 타입이며, 변경 불가능한 값(Immutable) 이다. (C는 배열이며, 자바는 객체로 표현한다.)

템플릿 리터럴(백틱(`))은 런타임에 문자열로 변경된다.

 

템플릿 리터럴

ES6 부터 새로운 문자열 표기법이 도입되었다.

템플릿 리터럴은 멀티라인 문자열, 표현식 삽입, 태그드 템플릿등 편리한 문자열 처리 기능을 제공한다.

런타임에 일반 문자열로 변환된다.

단 줄바꿈 등의 공백을 표현하려면 백슬래시를 활용해야 한다.

// 멀티라인 문자열
var str = `Hello
world.`;
//표현식 삽입
 var first = 'Hello';
 var last = 'world';
 console.log(`first is ${first}, last is ${world}`);
 console.log(`1 + 2 = ${1+2}`);

불리언 타입

논리적 참과 거짓을 나타내는 true, false뿐이다.

undefined 타입

undefined타입의 값은 undefined가 유일하다.

앞서, 변수를 선언한 이후 값을 할당하지 않은 변수를 참조하면 undefined가 반환되는 점을 배웠다.

즉, 개발자는 undefined로 초기화하는 것을 지양하고, null로 표현하는 것이 좋다. (명시적으로 값이 없다는 것을 알려줄 때)

 

null 타입

null타입의 값은 null이 유일하다. (Null, NULL은 해당하지 않는다.)

의도적으로 변수에 값이 없다는 것을 명시할 때 사용한다.

이는 이전에 할당되어 있던 값에 대한 참조를 명시적으로 제거하는 것이고, 자바스크립트 엔진은 누구도 참조하지 않은 메모리 공간에 대해 가비지 콜렉션을 수행한다.

함수가 유효한 값을 반환할 수 없는 경우 명시적으로 null을 반환하기도 한다.

 

심벌 타입

심벌(Symbol)은 ES6에서 추가된 7번째 타입으로, 변경 불가능한 원시 타입의 값이다.

심벌 값은 다른 값과 중복되지 않는 유일무이한 값이다.

주로, 이름이 충돌할 위험이 없는 객체의 유일한 프로퍼티 키를 만들 때 사용한다.

다른 원시 값은 리터럴을 통해 생성하지만, 심벌은 Symbol 함수를 통해 생성한다.

이 때, 생성된 심벌값은 외부에 노출되지 않고, 다른 값과 절대 중복되지 않는 유일한 값이다.

//심벌 값 생성
var key = Symbol('key');
console.log(typeof key); // symbol

//객체 생성
var obj = {};

//이름이 충돌할 위험이 없는 유일무이한 값이 심벌을 프로퍼티 키로 사용한다.
obj[key] = 'value';
console.log(obj[key]); // value

객체 타입

자바스크립트는 가장 크게 타입을 원시타입 객체타입으로 구분한다.

근본적으로 다르다고 할 수 있고, 자바스크립트를 이루고 있는 거의 모든 것이 객체이다.

객체 타입은 방대하므로, 이후에 별도로 정리하도록 하자.

데이터 타입의 필요성

  • 값을 저장할 때 확보해야 하는 메모리 공간의 크기를 결정하기 위해
  • 값을 참조할 때 한번에 읽어야 하는 메모리 공간의 크기를 결정하기 위해
  • 메모리에서 읽어들인 2진수을 어떻게 해석할지 결정하기 위해

동적 타이핑

정적 타입 언어는 변수 타입을 변경할 수 없고, 변수에 선언한 타입에 맞는 값만 할당 가능하다.

정적 타입 언어는 컴파일 시점에서 타입 체크를 수행한다.

타입 체크를 통과하지 못하면 에러를 발생시키고 실행을 막는다.

 

자바스크립트는 변수를 선언할 때 타입을 선언하지 않는다. 다만 var, let, const 키워드를 통해 변수를 선언할 뿐이다.

자바스크립트에서는 값을 할당하는 시점에 변수의 타입이 동적으로 결정되고 변수의 타입을 언제든지 자유롭게 변경할 수 있다.

자바스크립트의 변수는 선언이 아닌 할당에 의해 타입이 결정(타입 추론) 된다.

그리고 재할당에 의해 변수의 타입은 언제든지 동적으로 변할 수 있다. 동적 타이핑이 된다.

동적 타입 언어는 유연성은 높지만 신뢰성은 떨어진다.

연산자

연산자에 대해서는 기초적인 내용이라, 별도로 정리하진 않는다.

단, 새로운 개념이 등장하는 부분은 정리하고 넘어가자.

단축 평가

단축 평가 표현식 평가 결과
true || anything true
false || anything anything
true && anything anything
false && anything false

논리 연산자를 사용한 단축 평가 시, 무엇을 반환하는지를 알아볼 필요가 있다.

 

논리곱 연산자는 두 개의 피연사자가 모두 true 로 평가될 때, true를 반환한다.

그러나, 평가 결과가 불리언 값이 아닐 수 있다.

'Cat' && 'Dog' // -> "Dog"

좌항부터 우항으로 평가가 진행되며, 우항까지 평가가 되었을 때 평가 결과가 결정되므로, 두번째 피연산자를 반환한다(Dog)

'Cat' || 'Dog' // -> "Cat"

논리합 연산자는 하나만 true여도 true를 반환하므로, 첫번째 피연산자를 반환한다. (Cat)

여기서, 논리곱(&&)연산자와 논리합(||)연산자는 논리 연산의 결과를 결정하는 피연산자를 타입 변환하지 않고 그대로 반환한다.

 

단축 평가는 다음 같은 상황에서 유용하게 사용할 수 있다.

 

객체를 가리키기를 기대하는 변수가 null 또는 undefined가 아닌지 확인하고 프로퍼티를 참조할 때

var elem = null;
var value = elem.value; // TypeError: Cannot read property 'value' of null
var elem = null;
// elem이 null이나 undefined와 같은 Falsy 값이면 elem으로 평가되고
// elem이 Truthy값이면 elem.value로 평가된다.
var value = elem && elem.value; // null

함수 매개변수에 기본값을 설정할 때

함수를 호출할 때 인수를 전달하지 않으면 매개변수에는 undefined가 할당된다. 이때 단축 평가를 사용해 매개변수의 기본값을 설정하면 undefined로 인해 발생할 수 있는 에러를 방지할 수 있다.

// 단축 평가를 사용한 매개변수의 기본값 설정
function getStringLength(str) {
  str = str || '';
  return str.length;
}

// ES6의 매개변수 기본값 설정
function getStringLength(str = '') {
  return str.length;
}

옵셔널 체이닝 연산자

ES11에서 도입된 옵셔널 체이닝 연산자 ?.좌항의 피연산자가 null 또는 undefined인 경우 undefined를 반환하고, 그렇지 않으면 우항의 프로퍼티 참조를 이어간다.

var elem = null;

var value = elem?.value;
console.log(value); // undefined

이전 논리곱 연산자로 판단한것과 유사하지만, 논리 연산자 &&은 좌항 피연산자가 false로 평가되는 값 (false, undefined, null, 0, -0, NaN, '')이면 좌항 피연산자를 그대로 반환한다.

그러나, 옵셔널 체이닝 연산자는 null 또는 undefined가 아니면 우항의 프로퍼티 참조를 이어간다.

var str = '';

var length = str?.length;
console.log(length); // 0

null 병합 연산자

ES11에서 도입된 null 병합 연산자 ??는 좌항의 피연산자가 null 또는 undefined인 경우 우항의 피연산자를 반환하고, 그렇지 않으면 좌항의 피연산자를 반환한다.

var foo = null ?? 'default string';
console.log(foo); // default string

이 역시, 변수 기본값 설정에 유용하다.

논리합 연산자도 위 논리곱 연산자와 같은 이유가 있으며, null 병합 연산자는 옵셔널 체이닝과 같은 이유로 null / undefined만 판단한다.

var foo = '' || 'default string';
console.log(foo); // default string

var boo = '' ?? 'default string';
console.log(boo); // ''

제어문

제어문 역시 기초적인 내용으로, 별도 정리하지 않는다.

별도 사이트를 참고하도록 하자

https://ko.javascript.info/intro

 

자바스크립트란?

 

ko.javascript.info

 

이후에는 객체부터 알아볼 것이며, 스코프, 실행컨텍스트 등을 알아볼 예정이다.