항해

ssongyi·2022년 5월 20일
0

항해99

목록 보기
1/12

Javascript 자료형과 Javascript만의 특성

느슨한 타입(loosely typed)의 동적(dynamic) 언어

실행 도중에 변수에 예상치 못한 타입이 들어와 타입에러가 발생할 수 있다.

동적타입 언어는 런타임 시 확인할 수 밖에 없기 때문에, 코드가 길고 복잡해질 경우 타입 에러를 찾기가 어려워진다.

이러한 불편함을 해소하기 위해 TypeScipt나 Flow 등을 사용할 수 있다.

JavaScript 형변환

  • 문자형을 숫자형으로 변환하기

var 변수 = parseInt(문자); //문자를 정수형 숫자로 변환해줌

var 변수 = parseFloat(문자); //문자를 실수형 숫자로 변환해줌

var 변수 = Nember(문자); //문자를 정수&실수형 숫자로 변환해줌

  • 숫자형을 문자형으로 변환하기

    var 변수 = String(숫자); //숫자를 문자로 변환해줌

    var 변수 = 숫자.toString(진법); //숫자를 문자로 변환해줌 - 변환하면서 진법을 바꿀 수 있음

var 변수 = 숫자.toFixed(소수자리수); //숫자를 문자로 변환해줌 - 실수형의 소수점 자리를 지정할 수 있음

var 변수 = 숫자 + "문자열"; //숫자와 문자열을 한 문자열로 더해줌

==, ===

==연산자는 두 피연산자의 값의 타입이 다를 경우 자동으로 일부 피연산자의 타입을 변환 후 값을 비교해줌. 하지만 타입을 비교하지는 않으므로 ===보다는 느슨함.

=== 연산자는 타입 false 반환함, NaN 값은 자기 자신을 포함하여 어떠한 값도 일치하지 않는다. ===연산자에 NaN이 존재하면 항상 false

undefined와 null의 미세한 차이들을 비교해보세요.

  • undefined는 원시값(Primitive Type)으로, 선언한 후에 값을 할당하지 않은 변수나 값이 주어지지 않은 인수에 자동으로 할당된다. 이 값은 전역 객체의 속성 중 하나로, 전역 스코프에서의 변수이기도 하다. 따라서 undefined 변수의 초기 값은 undefined 원시 값이다.

-null은 원시값(Primitive Type) 중 하나로, 어떤 값이 의도적으로 비어있음을 표현한다. undefined는 값이 지정되지 않은 경우를 의미하지만, null의 경우에는 해당 변수가 어떤 객체도 가리키고 있지 않다는 것을 의미한다.

JavaScript 객체와 불변성이란 ?

기본형 데이터와 참조형 데이터

자바스크립트 데이터 타입은 크게 두가지인 원시형(Primitive Type)과 참조형(Reference Type)으로 분리됩니다.

기본(원시)형에는 Number, String, Boolean, null, undefined 가 있으며 ES6 에서는 Symbol 도 추가되었습니다.

참조형은 대표적으로 객체(Object)가 있고 그 하위에 배열(Array), 함수(Function), 정규표현식(RegExp) 등이 있으며, ES6에서는 Map, Set, WeakMap, WeakSet 등도 추가되었습니다.

두 타입의 가장 대표적인 차이로는 기본형에는 바로 값을 그대로 할당한다는 것이고 참조형에는 값이 저장된 주소값을 할당(참조)한다는 것입니다.

불변 객체를 만드는 방법

불변 객체란 참조하고 있는 데이터를 변경할 수 없는 객체를 의미합니다.

불변 객체를 사용하였을 때 장점은 외부에서 임의로 내부의 값을 제어할 수 없기 때문에 객체의 자율성이 보장되고 프로그램 내에서 변하지 않는 즉 고정된 부분이 많아짐으로써 프로그램 안정도를 높일 수 있습니다.

모든 객체를 불변으로 만들 필요는 없지만 변하지 않기를 바라는 객체를 불변객체로 만들어사용하자

얕은 복사와 깊은 복사

  • 얕은 복사
  1. 객체를 복사할 때, 해당 객체만 복사하여 새 객체를 생성한다.
  2. 복사된 객체의 인스턴스 변수는 원본 객체의 인스턴스 변수와 같은 메모리 주소를 참조한다.
  3. 따라서, 해당 메모리 주소의 값이 변경되면 원본 객체 및 복사 객체의 인스턴스 변수 값은 같이 변경된다.
  • 깊은 복사
  1. 객체를 복사 할 때, 해당 객체와 인스턴스 변수까지 복사하는 방식.
  2. 전부를 복사하여 새 주소에 담기 때문에 참조를 공유하지 않는다.

호이스팅과 TDZ는 무엇일까 ?

스코프, 호이스팅, TDZ

스코프

스코프(scope)란 사전적으로 '영역','범위' 라는 뜻을 가지고 있습니다. 자바스크립트에서는 이를 변수에 영향을 미칠 수 있는 범위 혹은 변수에 접근할 수 있는 범위로 이해할 수 있습니다. 이러한 관점에서 스코프는 전역(global) 스코프와 지역(local) 스코프로 분류할 수 있습니다.

전역 스코프란 변수가 함수 바깥에 선언되어 있거나, 변수 선언 시 var 키워드를 사용하지 않으면 변수는 전역 스코프에 포함됩니다.
함수 스코프란 지역 스코프의 대표적인 예시이며, 변수가 함수 내에서 선언되면 이 변수는 함수 스코프 내에서만 존재하게 됩니다.

자바스크립트의 변수는 변수가 접근할 수 있는 범위(스코프)에 따라 전역변수와 지역변수로 나눌 수 있습니다.
전역변수는 전역 스코프, 즉 함수 바깥에서 선언된 변수입니다. 따라서 전역변수는 프로그램의 전체에서 접근 가능합니다.
반면에 지역변수는 함수 스코프, 즉 함수 내부에서 선언된 변수로, 함수 내부에서만 접근 가능합니다.

호이스팅

호이스팅(Hoisting)이란, var 선언문이나 function 선언문 등을 해당 스코프의 선두로 옮긴 것처럼 동작하는 특성을 말합니다.
자바스크립트 엔진은 코드를 실행하기 전 실행 가능한 코드를 형상화하고 구분하는 과정을 거칩니다. 이 과정에서 모든 선언(var, let, const, function, class)을 스코프에 등록합니다.
이렇듯 선언이 코드 실행 보다 먼저 메모리에 저장되는 과정으로 인한 현상을 호이스팅이라 말합니다. 즉, 함수의 코드를 실행하기 전에 함수 선언에 대한 메모리부터 할당합니다. 덕분에 스크립트내에서 함수 선언의 위치는 중요하지 않게 되는 것입니다. 스크립트내에서 함수 호출을 함수 선언보다 먼저 해도 문제가 없습니다. 추가로, 이러한 호이스팅은 스코프 단위로 일어납니다.

TDZ
TDZ(Temporal Dead Zone)은 일시적인 사각 지대라는 뜻으로, 스코프 시작지점부터 초기화 시작지점 사이의 구간을 의미합니다. 다른 말로 변수가 선언되고 변수의 초기화가 이루어지기 전까지의 구간이라고 말할 수 있겠습니다. 자바스크립트에서 변수는 선언 - 초기화 - 할당 의 단계를 거쳐서 생성됩니다.

선언 단계(Declaration phase) : 변수를 실행 컨텍스트의 변수 객체에 등록하는 단계를 의미합니다. 이 변수 객체는 스코프가 참조하는 대상이 됩니다.
초기화 단계(Initialization phase) : 실행 컨텍스트에 존재 하는 변수 객체에 선언 단계의 변수를 위한 메모리를 만드는 단계 입니다. 이 단계에서 할당된 메모리에는 undefined로 초기화 됩니다.
할당 단계(Assignment phase) : 사용자가 undefined로 초기화된 메모리의 다른 값을 할당하는 단계 입니다.

함수 선언문과 함수 표현식에서 호이스팅 방식의 차이

함수 선언식은 함수 전체를 호이스팅 합니다. 정의된 범위의 맨 위로 호이스팅되서 함수 선언 전에 함수를 사용할 수 있다는 것입니다.

함수 표현식은 별도의 변수에 할당하게 되는데, 변수는 선언부와 할당부를 나누어 호이스팅 하게 됩니다. 선언부만 호이스팅하게 됩니다.

호이스팅은 var 변수 선언, 함수선언식에서만 일어납니다. let/const에서는 호이스팅이 발생하지 않는것 처럼 보입니다.

변수 선언의 3단계인 선언 단계, 초기화 단계, 할당 단계를 생각해 보면, var로 선언된 변수는 변수 선언전에 선언 단계와 초기화 단계를 동시에 진행합니다.
그래서 javascript는 실행 컨텍스트 변수 객체의 변수를 등록하고 메모리를 undefined로 만들어 버립니다.
그렇기 때문에 변수를 선언하기 전에 호출을 해도 undefined로 호출이 되는 호이스팅이 발생하는 것 입니다.

let으로 선언된 변수는 var 키워드와는 다르게 선언단계와 초기화 단계가 분리되어서 진행이 됩니다.

그렇기 때문에 실행 컨텍스트에 변수를 등록했지만,

메모리가 할당이 되질 않아 접근할 수 없어 참조 에러(ReferenceError)가 발생하는 것입니다. 그래서 let은 호이스팅이 되지 않는 것 처럼 보이지만 사실은 호이스팅이 되는 것입니다.

let, const, var, function 이 어떤 원리로 실행되는지

1. Var : 중복 선언 가능

var name = 'javascript';
console.log(name); // javascript

var name = 'react';
console.log(name); // react
Plain Text

var 로 선언한 변수는 동일한 이름으로 여러 번 중복해서 선언이 가능함. 이와 같은 경우, 마지막에 할당된 값이 변수에 저장됨. 위의 예제를 보면 에러 없이 각기 다른 값이 출력되는 것을 볼 수 있다.

이는 필요할 때마다 변수를 유연하게 사용할 수 있다는 장점이 될 수도 있지만, 기존에 선언해둔 변수의 존재를 잊고 값을 재할당하는 등의 실수가 발생할 가능성이 큼. 특히 코드량이 많아졌을 때, 같은 이름의 변수명이 여러 번 선언되었다면 어디 부분에서 문제가 발생하는지 파악하기 힘들뿐더러 값이 바뀔 우려가 있다.

이를 보완하기 위해 ES6부터 추가된 변수 선언 방식이 let 과 const 임.

2. let : 중복 선언 불가능, 재할당 가능

let name = 'javascript';
console.log(name); // javascript

let name = 'react';
console.log(name);
// Uncaught SyntaxError: Identifier 'name' has already been declared

name = 'vue';
console.log(name); // vue
Plain Text

var 와 다르게 let 은 해당 변수가 이미 선언되었다는 에러 메시지가 출력됨. 이처럼 중복 선언이 불가능하다.

name = 'vue' 와 같이 변수 선언 및 초기화 이후 반복해서 다른 값을 재할당 할 수는 있다.

3. const : 중복 선언 불가능, 재할당 불가능

const name = 'javascript';
console.log(name); // javascript

const name = 'react';
console.log(name);
// Uncaught SyntaxError: Identifier 'name' has already been declared

name = 'vue';
console.log(name);
// Uncaught TypeError: Assignment to constant variable
Plain Text

let 과 const 의 차이점은 immutable 의 여부다. let 은 변수에 다른 값을 재할당할 수 있지만, const 는 재할당 시 에러 메시지가 출력된다.

function func() {
const list = ["A", "B", "C"]

list = "D";
console.log(list);
// TypeError: Assignment to constant variable

list.push("D");
console.log(list); // ["A", "B", "C", "D"]

}

Plain Text

이처럼 const 는 constant(상수)를 뜻하기 때문에 한 번만 선언이 가능하며 값을 바꿀 수도 없다. 하지만 위 예제와 같이 배열과 오브젝트의 값을 변경하는 것은 가능하다.

결과적으로 const 는 불변을 의미하는 것과 다르게, 값을 재할당하는 코드만 불가능하다고 볼 수 있다.

+) 더 알아보기 : immutable array 를 만드는 방법
const list = ["A", "B", "C"];
const newList = [].concat(list, "D"); // concat(list, 배열에 추가하고자 하는 데이터)

console.log(newList); // ["A", "B", "C", "D"];
console.log(list === newList); // false
Plain Text

새롭게 만든 변수에 기존에 존재하던 배열과 객체를 할당할 때, 같은 데이터를 가진 새로운 배열 또는 객체가 생성되는 것이 아닌 원본과 같은 참조를 가지게 된다.

그렇기 때문에 새로 만든 변수의 값을 변경하면 원본 데이터도 바뀌게 되며, 이 경우 원본 데이터가 훼손되지 않도록 유지하는 방법이 필요하다. 위 예제와 같이 적용하면 기존 배열의 복사본이 생기는 것이기 때문에 원본에는 영향을 끼치지 않다.

ES6의 spread operator 를 사용하면 손쉽게 immutable array 를 만들 수 있음.

- 어떻게 사용하면 좋을까?
const 를 기본으로 사용하여 불필요한 변수의 재사용을 방지하고, 재할당이 필요한 경우 let 을 사용하는 것이 좋다.

실행 컨텍스트와 콜 스택
자바스크립트 코드가 실행되는 환경을 의미한다.
자바스크립트에서 대표적으로 두 가지 타입의 Execution context가 있다.

-- Execution context(실행 컨텍스트)

실행할 코드에 제공할 환경 정보들을 모아놓은 객체들로
자바스크립트의 동적 언어로서의 성격을 가장 잘 파악할 수 있는 개념이다.

  1. Global Execution context
    자바스크립트 엔진이 처음 코드를 실행할 때 Global Execution Context가 생성된다. 생성 과정에서 전역 객체인 Window Object (Node는 Global) 를 생성하고 this가 Window 객체를 가리키도록 한다.

  2. Function Execution context
    자바스크립트 엔진은 함수가 호출 될 때마다 호출 된 함수를 위한 Execution Context를 생성한다.
    모든 함수는 호출되는 시점에 자신만의 Execution Context를 가진다.

자바스크립트는 실행 컨텍스트가 활성화되는 시점에 다음과 같은 현상이 발생한다.

  • 호이스팅이 발생한다(선언된 변수를 위로 끌어올린다)
  • 외부 환경 정보를 구성한다
  • this 값을 설정한다.
  • call stack -- call stack
    코드가 실행되면서 생성되는 Execution Context를 저장하는 자료구조

엔진이 처음 script를 실행할 때, Global Execution Context를 생성하고 이를 Call Stack에 push한다.

그 후 엔진이 함수를 호출할 때 마다 함수를 위한 Execution Context를 생성하고 이를 Call Stack에 push 한다.

자바스크립트 엔진은 Call Stack의 Top에 위치한 함수를 실행하며 함수가 종료되면 stack에서 제거(pop)하고 제어를 다음 Top에 위치한 함수로 이동한다.

1줄 요약 : 프로그램이 함수 호출을 추적할때 사용한다.

스코프 체인, 변수 은닉화

- 스코프 체인

자바스크립트에서 전역 변수는 전역 객체의 프로퍼티이다. (ECMAScript 명세에 정의되어 있음)

지역 변수는 그런 규정이 없지만, 변수를 각 함수 호출과 연관된 객체(call object)의 프로퍼티로 생각할 수 있다.

지역 변수를 어떤 객체의 프로퍼티로 생각한다면, 자바스크립트의 모든 코드는 스코프 체인을 갖고 있다. 스코프 체인은 해당 코드의 유효 범위(in scope) 안에 있는 변수를 정의하는 객체의 체인, 리스트다.

변수 은닉화 = 캡슐화

  • 캡슐화는 중요한 것들은 외부에 보이지 않게 숨기거나 같은 것끼리 묶는 특징이 있다.

  • 특징 중 하나인 은닉화는 외부에서 접근을 할 수 없도록 막는 것을 말하며 간접적으로 접근이 가능하다.

  • 멤버 변수의 값을 세팅하거나 가져올 때 getter / setter 메소드를 사용한다.

콘솔에 찍힐 b 값을 예상해보고, 어디에서 선언된 “b”가 몇번째 라인에서 호출한 console.log에 찍혔는지, 왜 그런지 설명해보세요.
주석을 풀어보고 오류가 난다면 왜 오류가 나는 지 설명하고 오류를 수정해보세요.

0개의 댓글