JavaScript 기초 - 변수와 자료형

Kim-DaHam·2023년 2월 20일
0

JavaScript

목록 보기
1/18
post-thumbnail

🔥 학습목표

  • JavaScript의 정의, 실행환경에 대해 설명할 수 있다.
  • 변수와 자료형에 대해 설명할 수 있다.
  • 변수 keyword 종류와 그에 따른 스코프 차이를 설명할 수 있다.
  • JavaSCript Deep Dive 01~07장, 09장, 13~15장 공부&정리
  • 부록: CleanCode-변수 네이밍 규칙

🟣 JavaScript란?

브라우저, 서버, 모바일 개발이 가능한 멀티 패러다임 프로그래밍 언어이다.


⬜ JavaScript 엔진

JavaScript 코드를 실행할 수 있는 프로그램. 크롬에 내장된 v8이 대표적이다.


⬜ ECMAScript

자바스크립트의 표준 사양인 ECMA-262. 프로그래밍 언어의 값, 타입, 객체와 프로퍼티, 함수 등 핵심 문법을 규정한다.

즉, 자바스크립트는 일반적으로

프로그래밍 언어로서 기본 뼈대를 이루는 ECMAScript와 브라우저가 지원하는 클라이언트 사이드 Web API(DOM, Canvas, XMLHttpRequest 등)를 아우르는 개념이다.

🎁 Web API란?
🎁 Web API & REST


⬜ Node.js

구글 v8 자바스크립트 엔진으로 빌드된 자바스크립트 런타임 환경

브라우저의 자바스크립트 엔진에서만 동작하던 자바스크립트를 브라우저 이외의 환경에서도 동작할 수 있도록 자바스크립트 엔진을 브라우저에서 독립시킨 자바스크립트 실행 환경이다.

javascript로 브라우저 뿐만 아니라 서버를 구축하고, 서버에서 JavaScript가 작동되도록 해주는 런타임 환경(플랫폼)이라고 생각하면 된다.

=> 간략: 브라우저 외부에서 자바스크립트 실행 환경을 제공한다.


⬜ SPA 프레임워크

웹 애플리케이션의 개발 규모와 복잡도가 상승하면서 필요에 따라 많은 패턴과 라이브러리가 출현했다. 덕분에 개발에는 많은 도움을 주엇으나 변경이 유연하면서 확장하기 쉬운 애플리케이션 아키텍처의 구축을 어렵게 했고, 필연적으로 프레임워크가 등장하게 되었다.

그 중 SPA(Single Page Application)가 대중화 되면서 Angular.js, React.js, Vue.js, Svelte 등 다양한 SPA 프레임워크/라이브러리들이 탄생했다.

  • 여러 페이지를 링크로 연결하지 않기 때문에 불필요한 로드가 발생하지 않음.
  • Ajax 기술을 이용하여 서버와 JSON 문자열로 데이터를 주고 받음.
  • 데이터가 변경되는 부분만 바뀜. 페이지가 변할 때마다 모든 내용을 Redirect할 필요가 없음.
  • JavaScript 비동기 통신 관련 기술을 기반으로 함.

🎁 SPA란?


⬜ JavaScript는 컴파일러 언어? 인터프리터 언어?

둘 다 복합적으로 이루어진다.

sum함수가 있다고 치자. 컴파일러 언어의 경우 sum 함수의 결과값은 미리 기계어로 번역되어 정해져 있다. 반면 인터프리터는 한 줄 씩 실행되기 때문에 sum 함수를 만날 때마다 일일히 실행한다. 함수 안에 복잡한 반복문이 있다면 모두 거쳐야 결과가 도출된다.

이러한 인터프리터의 단점을 개선하기 위해 v8 엔진이 나타나고 자바스크립트도 컴파일 과정을 거치게 되었다.

<기존의 자바스크립트>
JavaScript code → Parser → AST → Interpreter → Bytecode

<개선 된 자바스크립트>
Profiler가 등장한다. 이는 인터프리터를 관찰하며 실행 코드를 계속해서 모니터링한다. 코드 내 반복 실행되는 것이 있다면 이를 컴파일러에게 넘겨 실시간 컴파일 하고 최적화 된 Bytecode를 생성한다.

이처럼 필요할 때마다 컴파일 하는 컴파일러를 JIT(Just-In-Time)라고 한다.

🎁 Compiler? Interpreter? 자세한 내용


⬜ Vanila JavaScript

외부 라이브러리를 사용하지 않거나 최소한으로 사용하여 작성한 자바스크립트 코드.


⬜ Web Browser

  • HTML 문서 내 <body> 의 마지막 부분에 <script> 작성을 권장.
  • 브라우저 마다 보여지는 결과가 다를 수 있으므로 크로스 브라우징 체크 필수(대표적으로 사용되는 거 몇 개 정도만)



🟣 변수

⬜ 변수 선언

var, let, const 키워드를 사용한다.

🔴 주로 let, const만 사용해야 한다. (이후 설명)

var score; // undefined

위와 같이 var 변수를 선언할 시 자바스크립트에서 제공하는 원시 타입 값 undefined가 할당 된다.(이를 암묵적인 초기화 라고 한다.)

var score = 100;

변수 선언은 선언 단계와 초기화 단계를 동시에 진행할 수도 있다. 다만 자바스크립트 엔진은 저렇게 단축 표현해도 변수 선언과 값의 할당을 2개의 문으로 나누어 각각 실행한다.

  • 변수선언은 소스코드가 순차적으로 실행되는 런타임 이전에 먼저 실행 (undefined로 초기화)
  • 값의할당런타임에 실행

⬜ 호이스팅

console.log(score); // undefined
var score = 80; // 값의 할당
console.log(score); // 80

위 코드에서 var score을 선언 및 할당하기도 전에 콘솔에 출력하면 에러가 뜨지 않고 undefined를 출력한다.

바로 런타임 이전에 변수 선언과 함께 undefined로 암묵적 초기화가 발생하기 때문이다.

이렇게 변수 선언문이 코드의 선두로 끌어 올려진 것처럼 동작하는 자바스크립트 고유의 특징을 변수 호이스팅이라고 한다.


⬜ 값의 재할당

var score = 80;
score = 100;

위와 같이 값을 재할당 하면 값 80이 저장되어 있던 메모리 공간을 지우고 그 메모리 공간에 할당하는 것이 아닌, 새로운 메모리 공간을 확보하고 그 메모리 공간에 숫자 값 100을 저장한다.

그리고 기존의 80을 담고있던 메모리 공간은 score라는 식별자를 잃게 되며 가비지 콜렉터(garbage collector)를 통해 어떤 식별자도 참조하지 않는 메모리로써 공간을 해제 당한다.


⬜ 식별자 네이밍 규칙

  • var firstName: 카멜 케이스. 변수나 함수 이름에 사용
  • var FirstName: 파스칼 케이스. 생성자 함수, 클래스 이름에 사용

⬜ 데이터 타입

🔴 NaN, null 대소문자 헷갈리지 말자.



🟣 연산자

⬜ 단항 산술 연산자

var x = '1';

console.log(+x); // 1 문자열을 숫자 타입으로 변환한다.
console.log(x); // "1" 부수 효과는 없다.

⬜ 비교연산자

NaN === NaN // false
Number.isNaN(NaN); // true
Number.isNaN(1 + undefined) // true

Nan은 자신과 일치하지 않는 유일한 값이다.
따라서 숫자가 NaN인지 조사하려면 빌트인 함수 Number.isNaN()을 사용해야 한다.

🔵 Object.is 메서드
비교 연산자(===)는 +0과 -0을 동일하다고 판단한다. 또한 NaN과 NaN을 비교하면 다른 값이라고 한다.

보다 정확한 비교를 위해서는 Object.is 메서드를 사용한다.

Object.is(NaN, NaN); // true

⬜ 삼항 조건 연산자

조건식? 조건식이 true일 때 반환값 : 조건식이 false일 때 반환값


⬜ typeof 연산자

🔴 nulltypeof 연산자로 확인할 시 object 데이터 타입을 반환한다. 따라서 값이 null 타입인지 확인할 때는 일치 연산자(===)를 사용해야 한다.


⬜ 타입 변환과 단축 평가

< 타입 변환 >

  • 명시적 타입 변환(explicit coercion), 타입 캐스팅
  • 암묵적 타입 변환(implict coercion), 타입 강제 변환
var x = 10;

var str = x + '';
console.log(typeof str, str); // string 10
// x 값이 변한 건 아니다.
console.log(typeof x, x) // number 10

위와 같은 방법으로도 숫자→문자열 타입 변환이 가능하다.

자바스크립트 엔진은 표현식 x + '' 을 평가하기 위해 x 변수의 숫자 값을 바탕으로 새로운 문자열 '10'을 생성하고 이것으로 '10' + '' 를 평가한다. 이때 암묵적으로 생성된 문자열 '10' 은 재할당 되지 않는다.

자신이 작성한 코드에서 암묵적 타입 변환이 발생하는지 예측 가능해야 한다. 자바스크립트 문법을 잘 이해하고 있는 개발자에게는 (10).toString() 보다 10+'' 이 더욱 간결하고 이해하기 쉽다.

=> 라고.. JavaScript DeepDive에서는 그렇게 말하는데 솔직히 나라면 몇자 더 치더라도 toString() 코드를 주욱 읽어나갈 때 가독성이 더 좋을 거 같은데.. 잘 모르겠다. 그렇다면 그런 줄 알자. 남이 쓰자면 쓰겠지만 혼자선 저렇게 안 쓸 듯.


< 단축 평가 - 옵셔널 체이닝 연산자 ?. >

?. : 좌항이 null 또는 undefined일 경우 undefined 를 반환하고, 그렇지 않으면 우항의 프로퍼티 참조를 이어간다.

var elem = null;

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

var length = str && str.length; 와 같이 && 연산자로 표현하는 방법도 있다.

허나 차이점은

  • && : 좌항 피연산자가 Falsy 값이면 무조건 우항 피연산자를 평가한다.(0이나 ''은 객체로 평가될 때도 있다.)
  • ?. : 좌항 피연산자가 Falsy 값이더라도null 이나 undefined가 아니면 우항의 프로퍼티 참조를 이어간다.

< 단축 평가 - null 병합 연산자 >

?? : 좌항의 피연산자가 null 혹은 undefined 인 경우 우항의 피연산자를 반환하고, 그렇지 않으면 좌항의 피연산자를 반환한다.



🟣 스코프

=> 식별자가 유효한 코드 범위

스코프 체인 : 스코프가 계층적으로 연결된 것.

  • 전역 스코프 : 코드의 가장 바깥 영역
  • 지역 스코프 : 함수 몸체 내부. 코드블록(if, for문)이 아닌 함수에 의해서만.

⬜ 변수 키워드에 따른 스코프

  • var : 같은 스코프 내에서 중복 선언 허용. 함수 레벨 스코프로, 함수의 코드 블록만을 지역 스코프로 인정.
  • let, const : 같은 스코프 내에서 중복 선언 비허용. 블록 레벨 스코프로, if, for, while 등의 코드블록도 지역 스코프로 인정.



🟣 let, const 키워드

⬜ let

  • let 으로 선언한 변수는 "선언 단계"와 "초기화 단계" 가 분리되어 진행 된다.
  • 자바스크립트 엔진에 의해 암묵적으로 선언 단계 먼저 수행
  • 초기화 단계는 변수 선언문에 도달했을 때 실행
  • 초기화 단계 실행되기 전에 변수 접근 시 참조 에러.
  • 스코프 시작 지점부터 초기화 시작 지점까지 변수 참조 불가. == 일시적 사각지대 TDZ

< 변수 호이스팅이 일어나지 않는가? >
🔴 호이스팅 일어난다.

let foo = 1; // 전역 변수
{
	console.log(foo); // 초기화 되지 않은 참조 에러
    let foo = 2; // 지역 변수
}

만약 호이스팅 되지 않았더라면 전역 변수에서 let이 선언&초기화 되었으므로 1을 반환해야 한다.

하지만 스코프 내에서 호이스팅이 일어나기 때문에 코드 블록 내의 지역 변수 foo를 별도 선언하고, 초기화 단계 실행(변수 선언문 도달) 전에 접근 했으므로 참조 에러가 나타난다.


⬜ const

🔴 선언과 초기화를 동시에 해야한다.
🔵 상수(변하지 않는 값)으로 사용한다.



🟣 부록 - Clean Code

애자일 소프트웨어 장인 정신 / 클린 코드 - 로버트 C. 마틴

" 좋은 이름을 지으려면 시간이 걸리지만 좋은 이름으로 절약하는 시간이 훨씬 더 많다. 그러므로 이름을 주의 깊게 살펴 더 나은 이름이 떠오르면 개선하기 바란다."

⬜ 2장. 의미있는 이름

의도를 분명히 밝혀라.

아래 질문에 모두 답할 수 있는 변수, 함수, 클래스 이름을 작성해라.

  • 존재 이유는 무엇인가?
  • 수행 기능은 무엇인가?
  • 사용 방법은 무엇인가?
int d; // x

int elapsedTimeInDays; // o
int daysSinceCreation; // o
int daysSinceModification; // o
int fileAgeInDays; // o
const STATUS_VALUE = 0;
const FLAGGED = 4;

public List<int[]> getFlaggedCells() { // 1. 무얼 수행하는 함수인가?
	List<int[]> flaggedCells = newArrayList<int>(); // 2. 함수가 반환하는 리스트를 어떻게 사용하는가?
    for(int[] cell : gameBoard) // 3. 무슨 리스트의 원소를 뽑아오는가?
    	if (cell[STATUS_VALUE] == FLAGGED) // 4. gameBoard에서 0번째 값이 왜 중요하며 값 4는 무슨 의미인가?
	flaggedCells.add(cell);
    return flaggedCells; 
}

// 한 번 더 수정
public List<Cell> getFlaggedCells() { // int 배열 대신 칸을 간단한 클래스로 만듦
	List<Cell> flaggedCells = newArrayList<Cell>();
    for(Cell cell : gameBoard)
    	if (cell.isFlagged()) // isFlagged 라는 좀 더 명시적인 함수 사용
	flaggedCells.add(cell);
    return flaggedCells; 
}

그릇된 정보를 피하라

  • 나름대로 널리 쓰이는 의미가 있는 단어를 다르 의미로 사용하지 마라.
    • Ex) 직각삼각형의 빗변(hypotenuse)를 hp라고 약어로 쓰고싶겠지만 hp, aix, sco는 유닉스 플랫폼이나 유닉스 변종을 가리키는 이름이다.
  • 여러 계정을 그룹으로 묶을 때, 실제 List가 아니라면 accountList라 명명하지 않는다.
    • accountGroup, bunchOfAccounts, Accounts 라 명명한다.
  • 서로 흡사한 이름을 사용하지 마라.

의미 있게 구분하라

  • a1, a2, a3 … 와 같이 연속적인 숫자를 덧붙인 이름은 쓰지 마라.
  • Info나 Data는 의미가 불분명한 용어이다.
  • 중복되는 의미의 단어를 쓰지 마라. 변수 이름에 variable, 표 이름에 table은 금물이다.
  • 명확한 관례가 없다면 구분이 안 된다. 읽는 사람이 차이를 알도록 이름을 지어라. (getActiveAccount(), getActiveAccounts, getActiveAccountInfo() 이런 식으로 하면 어느 함수를 호출해야 하는지 헷갈린다.)

발음하기 쉬운 이름을 사용하라

검색하기 쉬운 이름을 사용하라

인코딩을 피하라


자신의 기억력을 자랑하지 마라

  • 루프에서 반복 횟수를 세는 i, j, k는 괜찮다.(l 은 절대 안 된다! - 1이랑 헷갈리기 때문. )
  • a와 b를 사용하므로 c를 선택한다는 논리의 작명은 최악이다.

클래스 이름

  • 명사, 명사구
  • Customer, WikiPage, Account, AddressParser
  • 동사는 사용하지 않는다.

메서드 이름

  • 동사, 동사구
  • postPayment, deletePage, save

기발한 이름은 피하라

  • 재미난 이름보다 명료한 이름을 선택하라.

한 개념에 한 단어를 사용하라

  • 동일 코드 기반에 controller, manager, driver 를 섞어 쓰면 혼란스럽다.저 세 개가 근본적으로 어떻게 다른가?

말장난을 하지 마라

  • 한 단어를 두 가지 목적으로 사용하지 마라. 기존 값을 더하거나 새로 생성하면 add, 집합에 값 하나를 추가하면 insert 혹은 append 가 좋다.

해법 영역에서 가져온 이름을 사용하라.

  • 기술 개념에는 기술 이름이 가장 적합한 이름이다.

문제 영역에서 가져온 이름을 사용하라.

  • 적절한 프로그래머 용어가 없다면 문제 영역에서 이름을 가져온다. 그러면 코드를 보수하는 프로그래머가 분야 전문가에게 의미를 물어 파악할 수 있다.

의미있는 맥락을 추가하라

불필요한 맥락을 없애라

  • 일반적으로는 짧은 이름이 긴 이름보다 좋다. 단, 의미가 분명한 경우에 한해서다. 이름에 불필요한 맥락을 추가하지 않도록 주의하자.
profile
다 하자

0개의 댓글