본문 바로가기
기술 개발/Javascript

About JavaScript

by 쪼짱 2022. 7. 19.
728x90
반응형
SMALL

JavaScript의 자료형과 JavaScript만의 특성은 무엇일까 ?

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

  • JavaScript는 느슨한 타입(loosely typed)의 동적(dynamic) 언어입니다. JavaScript의 변수는 어떤 특정 타입과 연결되지 않으며, 모든 타입의 값으로 할당 (및 재할당) 가능합니다.
  • 동적(dynamic)언어
    • 동적언어는 사용자가 주는 정보를 토대로 웹페이지가 유동적으로 변경할 수 있게 만들어주는 언어입니다. 동적언어인 javascript로 코드를 만들면 만든 코드에 따라 어떤 행동을 했을 때 경고문이 보여진다거나 버튼을 눌렀을 때 웹페이지를 어두워지게 만들어지는 등 사용자가 주는 정보에 따라 웹페이지를 변화 시킬 수 있습니다.

2. JavaScript 타입 변환

  • 묵시적 타입 변환(implicit type conversion) 
    • 자바스크립트는 특정 타입의 값을 기대하는 곳에 다른 타입의 값이 오면, 자동으로 타입을 변환하여 사용합니다.
    • 즉, 문자열 값이 오길 기대하는 곳에 숫자가 오더라도 자바스크립트는 알아서 숫자를 문자열로 변환하여 사용합니다.
    • 쉽게 말하자면, 숫자보다 문자열이 우선시 됩니다.
  •  명시적 타입 변환(explicit type conversion)
      1. Number()
      2. String()
      3. Boolean()
      4. Object()
      5. parseInt()
      6. parseFloat()명시적 타입 변환을 위해 자바스크립트가 제공하는 전역 함수

- 이 외에도 숫자를 문자열로 반환, 불리언 값을 문자열로 변환, 날짜를 문자열이나 숫자로 변환, 문자열을 숫자로 변환, 불리언 값을 숫자로 변환하는 방법들을 보여주고 있습니다.

 

코딩교육 티씨피스쿨

4차산업혁명, 코딩교육, 소프트웨어교육, 코딩기초, SW코딩, 기초코딩부터 자바 파이썬 등

tcpschool.com

 

3. 동등 연산자(==)와 일치 연산자(===)

    • 동등 연산자(==, equal)와 일치 연산자(===, strict equal)는 모두 두 개의 피연산자가 서로 같은지를 비교해 줍니다. 두 연산자 모두 피연산자의 타입을 가리지는 않지만, 그 같음을 정의하는 기준이 조금 다릅니다.
    • ===: 왼쪽 피연산자와 오른쪽 피연산자의 값이 같고, 같은 타입이면 참을 반환합니다.
      • 일치 연산자(===)는 타입의 변환 없이 두 피연산자의 값이 같고, 타입도 같아야만 참(true)을 반환합니다.
    • ==: 왼쪽 피연산자와 오른쪽 피연산자의 값이 같으면 참을 반환합니다.
      • 동등 연산자(==)는 두 피연산자의 값이 서로 같으면 참(true)을 반환합니다. 이때 두 피연산자의 타입이 서로 다르면, 비교를 위해 강제로 타입을 같게 변환합니다.
var x = 3, y = '3', z = 3;
document.write((x == y) + "<br>");  // x와 y의 타입이 서로 다르므로 타입을 서로 같게 한 후 비교를 하므로 true
document.write((x === y) + "<br>"); // x와 y의 타입이 서로 다르므로 false
document.write(x === z);            // x와 z은 값과 타입이 모두 같으므로 true

 

4. 느슨한 타입(loosely typed)의 동적(dynamic) 언어의 문제점과 보완 방법

  • 실행 도중에 변수에 예상치 못한 타입이 들어와 타입에러가 발생할 수 있습니다.
  • 동적타입 언어는 런타임 시 확인할 수 밖에 없기 때문에, 코드가 길고 복잡해질 경우 타입에러를 찾기 어려워집니다. 따라서, TypeScript나 Flow등을 사용하여 보완할 수 있습니다.

 

5. undefined와 null 비교

  • 자바스크립트에서 null이란 object 타입이며, 아직 '값'이 정해지지 않은 것을 의미합니다.
  • 또한, undefined란 null과는 달리 '타입'이 정해지지 않은 것을 의미합니다. 따라서 자바스크립트에서 undefined는 초기화되지 않은 변수나 존재하지 않는 값에 접근할 때 반환됩니다.

 


JavaScript 객체와 불변성이란 ?

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

https://webclub.tistory.com/638

기본형 데이터 참조형 데이터
숫자(number)
문자열(string)
불리언(boolean)
심볼(symbol) - ECMAScript6
undefined
객체(object)
- 배열(Array)
- 함수(Function)
- 날짜(Date)
- 정규표현식(RegExp)
  (+ ES6에서 추가 된 것)
- Map
- WeakMap
- Set
- WeakSet
  • 기본형 데이터
    • 기본형 데이터는 값을 그대로 할당함 
    • 메모리 내에 고정된 크기로 저장되면서, 원시 데이터 값 자체를 보관하며 불변성을 가짐
    • 기본적으로 데이터는 하나의 메모리를 사용함
    • 데이터 영역의 데이터는 한 번 생성 되었을 경우 수정이 안되며, 새로운 데이터일 경우 비어있는 데이터 영역에 새로 할당 됨
    • 새로 할당된 데이터 영역의 주소값을 변수 영역의 데이터 주소값으로 재할당함
    • 불변성은 효율적으로 데이터를 저장하기 위해 생김
    • 변수 선언 -> 데이터 재할당 -> 변수에 변수를 대입
  • 참조형 데이터
    • 값이 저장된 주소값을 할당(참조)함
    • 참조형은 기본형 데이터의 집합
    • 메모리 저장 방식: 변수 선언 -> 할당과정에서 참조형 데이터인 것을 인식하고 프로퍼티/데이터(key/value)인 것을 확인
    • 불변성 & 가변성 둘다 가짐
  • 용어 정리
    • 할당: 해당 변수가 가리키는 주소의 공간에 데이터를 저장하는 과정
    • 선언: 공간을 확보하고 변수명과 주소를 매칭시키는 과정

 

 

2. JavaScript의 형 변환

자바스크립트는 형 변환이 필요할 때, 원하는 메서드를 찾고 호출함

  • Symbol.toPrimitive
  • Object.toString()
    • 문자열을 반환하는 object의 대표적인 방법
    • 기본적으로 toString() 메서드는 Object에서 비롯된 모든 객체에 상속됨.
    • 이 메서드가 사용자 지정 개체에서 재정의되지 않으면 toString()은 "[object type]"을 반환함.
    • var o = new Object();
      o.toString();     // returns [object Object]
    • obj.toString()은 로깅이나 디버깅 목적으로도 자주 사용됨
  • Object.valueOf()
    • 특정 객체의 원시 값을 반환함.
    • 어떤 객체가 원시값을 가지고 있지 않다면, valueOf는 객체 스스로를 반환함
    • MyNumberType.prototype.valueOf = function() { return customPrimitiveValue; };

 

 

3. 불변 객체를 만드는 방법

  • 불변객체
    • 불변객체란 상태값을 수정할 수 없는 객체를 의미
    • 즉, 객체를 처음 생성(초기화) 후에는 객체가 가지는 상태를 변경할 수 없는 것을 의미
    • 이러한 불변객체의 특성은 어플리케이션을 만드는데 있어 많은 도움을 줌
    • 불변 객체는 상태가 변하지 않기 때문에 단순함
      가변 객체는 변경자 메소드 호출로 인해 어떻게 상태가 바뀔지 예측하기 힘듦
    • 또한 Multi Threading 환경에서 Thread Safety를 보장하고, 상수로서 Cache 사용하기도 용이
  • 불변객체 만드는 방법
      • 멤버변수에 private final을 붙인다.
      • getter가 있다고 setter를 무조건 만들지 말자.
      • final class로 선언하여 상속을 막자.
      • 혹은 모든 생성자를 private로 제한하고, 정적 팩토리 메소드를 통해서만 객체를 생성할 수 있게 하자.
      • 생성자의 인자로 Reference Type을 받을 때는 Deep Copy를 해서 맴버변수에 저장하자.
      • getter를 통해서 Reference Type의 맴버를 반환할 때는 Deep Copy후 반환하자.

 

4. 얕은 복사와 깊은 복사

  • 얕은 복사 Shallow Copy
    • 얕은 복사란 객체를 복사할 때 위의 예제처럼 원래값과 복사된 값이 같은 참조를 가리키고있는 것을 말한다. 객체안에 객체가 있을 경우 한개의 객체라도 원본 객체를 참조하고 있다면 이를 얕은 복사라고 한다.
    • 얕은 복사의 문제점 : 복사하려는 객체의 내부에 존재하는 객체는 완전한 복사가 이루어지지 않는다.
    • Object.assign: 메소드는 열거할 수 있는 하나 이상의 출처 객체(source)로부터 대상 객체(target)로 속성을 복사할 때 사용하고 대상 객체(target)를 반환
    • 전개연산자: {...obj}
  • 깊은 복사 Deep Copy
    • 깊은 복사된 객체는 객체안에 객체가 있을 경우에도 원본과의 참조가 완전히 끊어진 객체를 말한다.
    • 재귀함수를 이용한 복사
    • JSON.parse(JSON.stringify(obj))
      • JSON.stringify : 자바스크립트 객체를 JSON 문자열로 변환
      • JSON.parse : JSON 문자열을 자바스크립트 객체로 변환
      • JSON 문자열로 변환했다가 다시 객체로 변환해주기 때문에 객체에 대한 참조가 없어지는 것이다.
    • Lodash의 clonedeep 메소드를 사용
      • _.cloneDeep(obj)
      • JSON.parse(JSON.stringify()) 방법의 문제점이었던 함수 복사도 가능

 

 

<출처>

https://okayoon.tistory.com/entry/%EC%BD%94%EC%96%B4-%EC%9E%90%EB%B0%94%EC%8A%A4%ED%81%AC%EB%A6%BD%ED%8A%B8-%EB%8D%B0%EC%9D%B4%ED%84%B0-%ED%83%80%EC%9E%85-%EA%B8%B0%EB%B3%B8%ED%98%95-%ED%83%80%EC%9E%85Primitive-Type%EA%B3%BC-%EC%B0%B8%EC%A1%B0%ED%98%95-%ED%83%80%EC%9E%85Reference-Type

https://velog.io/@jayjungzzzz/%EA%B8%B0%EB%B3%B8%ED%98%95%EA%B3%BC-%EC%B0%B8%EC%A1%B0%ED%98%95%EC%9D%98-%EC%A2%85%EB%A5%98-%EB%B0%8F-%EC%B0%A8%EC%9D%B4%EC%A0%90

 

 


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

1. 스코프, 호이스팅, TDZ

  • 스코프(Scope:범위, 영역)
    • 식별자(변수, 함수, 클래스 이름)가 유효한 범위 → 선언 위치에 따라 유효 범위가 결정됨: 이름 충돌 방지, 메모리 절약
  • 호이스팅(Hoisting)
    • 자바스크립트 엔진(번역기, Interpreter)이 코드를 실행하기 전, 변수, 함수, 클래스의 선언문을 끌어 올리는 것을 말함
  • TDZ (Temporal Dead Zone)
    • TDZ 시맨틱은 선언 전에 변수에 접근하는 것을 금지한다. TDZ는 징계를 내린다
    • TDZ의 영향을 받는 구문
      1. const 변수: const 변수는 선언한 후에 사용해야 한다.
      2. let 변수: let변수도 선언 이후에 사용해야 한다.
      3. class 구문: 클래스를 선언한 후에 사용하도록 수정한다.
      4. constructor() 내부의 super(): 부모 클래스를 상속받았다면, 생성자 안에서 super()를 호출하기 전까지 this바인딩은 TDZ에 있다. TDZ는 인스턴스를 초기화하기 위해 부모 클래스의 생성자를 호출할 것을 제안한다. 부모 클래스의 생성자를 호출하고 인스턴스가 준비되면 자식 클래스에서 this 값을 변경할 수 있다.
      5. 기본 함수 매개변수: 기본 매개변수는 글로벌과 함수 스코프 사이의 중간 스코프(intermidiate scope)에 위치한다. 기본 매개변수 또한 TDZ 제한이 있다. 기본 매개변수는 선언 및 초기화 다음에 사용되어야 한다.

TDZ는 const, let, class 구문의 유효성에 영향을 미치는 중요한 개념이다. TDZ는 선언 전에 변수를 사용하는 것을 허용하지 않는다. 반대로 var 변수는 선언 전에도 사용할 수 있기 때문에  var 사용은 피하는 것이 좋다.

  • 변수 선언 전에 어떤 것도 사용하지 않는다.
  • 변수의 선언과 초기화를 분리한 후, 선언만 코드의 최상단으로 옮김
  • { const a = 'a'; } console.log(a); // 블럭 외부에서 블럭 내부의 변수를 참조할 수 없음 const b = 'b';
  • 코드블럭{} 안의 변수는 블럭 안에서만 유효

 

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

console.log(hi);
let hi = hi;

let func1 = fuction () {};

const cat = new Cat();
class Cat {}
// error

→ 함수의 호이스팅은 함수의 선언문 전에 호출이 가능하게 해줌

→ 변수(let, const)와 클래스는 선언만 호이스팅이 되고, 초기화는 안됨

→ 초기화 전, 변수에 접근하면 컴파일(빌드)에러가 발생

→ 함수의 선언문은 선언 이전에도 호출이 가능함

 

 

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

  • 변수 Variables
    • 값을 저장하는 공간
    • 자료를 저장할 수 있는 이름이 주어진 기억장소
    • let
      • 재할당이 필수로 필요한 경우
    • const
      • 값을 재할당할 필요가 없는 경우
    • var
      • 변수 선언하는 키워드 없이 선언 & 할당이 가능함(선언인지, 재할당인지 구분하기 어려움)
      • 블록 레벨 스코프 안됨
      • 함수 레벨 스코프만 지원 됨
      • 중복 선언이 가능함

 

4. 실행 컨텍스트와 콜 스택(Execution context)

variable object { vars, function declarations, arguments… }
Scope chain [ Variable object + all parent scopes ]
thisValue Context object
  • 실행 컨텍스트
    • 자바스크립트 코드가 실행되는 환경
    • 실행할 코드에 제공할 환경 정보들을 모아놓은 객체
    • 실행 가능한 코드를 형상화하고 구분하는 추상적인 개념
    • 자바스크립트는 기본적으로 동기적으로 진행
  • Callstack(콜 스택)
    • 여러 함수들(functions)을 호출하는 스크립트에서 해당 위치를 추적하는 인터프리터 (웹 브라우저의 자바스크립트 인터프리터같은)를 위한 메커니즘
    • 자바스크립트 코드가 실행되며 생성되는 실행 컨텍스트를 저장하는 자료구조
  • 실행 컨텍스트가 실행되는 순서
    • 엔진이 처음 script를 실행할 때, 전역 실행 컨텍스트를 생성하고 이를 Call Stack에 push
    • 그 후 엔진이 함수를 호출할 때 마다 함수를 위한 실행 컨텍스트를 생성하고 이를 Call Stack에 push 한다.
    • 자바스크립트 엔진은 Call Stack의 Top에 위치한 함수를 실행하며 함수가 종료되면 stack에서 제거(pop)하고 제어를 다음 Top에 위치한 함수로 이동한다.
  • 자바스크립트는 실행 컨텍스트가 활성화되는 시점에 다음과 같은 현상이 발생
    • 호이스팅이 발생(선언된 변수를 위로 끌어올린다)
    • 외부 환경 정보를 구성
    • this 값을 설정

 

5. 스코프 체인, 변수 은닉화

  • 스코프 체인
    • 자바스크립트 엔진은 변수(식별자)를 찾을 때 일단 자신이 속한 스코프에서부터 찾아보고, 그 스코프에 찾는 변수가 없으면 상위 스코프를 타고 올라가며 차례차례 찾아 나간다. 이것을 스코프 체인(Scope Chain)이라고 하며, 스코프가 중첩되어있는 모든 상황에서 발생한다.
    • 상위 스코프에서 하위 스코프에 선언된 변수로는 접근할 수 없다.
  • 변수 은닉화(캡슐화)
    • 은닉화란? 직접적으로 변경되면 안 되는 변수에 대한 접근을 막는 것
    • 클로저를 통한 은닉화
    • 자바스크립트에서 클로저는 함수가 생성되는 시점에 생성된다.
    • 함수가 생성될 때 그 함수의 렉시컬 환경을 포섭(closure)하여 실행될 때 이용한다.

 

<출처>

호출 스택 - 용어 사전 | MDN

TDZ을 모른 채 자바스크립트 변수를 사용하지 말라

Scope | PoiemaWeb

Execution Context | PoiemaWeb

[딥다이브] 6월 1주차 - 15강 let, .. : 네이버블로그 (naver.com)

[JS] 실행 컨텍스트(Execution Context) (tistory.com)

https://intrepidgeeks.com/tutorial/js-encapsulation

 


실습 과제

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

 

let b = 1;
function hi () {
  const a = 1;
  let b = 100;
  b++;
  console.log(a,b); 
}
// console.log(a);
console.log(b); 
hi();
console.log(b);
let b = 1;
function hi () {
  const a = 1;
  let b = 100;
  b++;
  console.log(a,b); 
  // console.log(a); //블록스코프
}
console.log(b); // 1번째줄 b
hi(); // 4,5번째줄 b 함수호이스팅
console.log(b); // 1번째줄 b

 

728x90
반응형
LIST

'기술 개발 > Javascript' 카테고리의 다른 글

Callback 함수  (0) 2022.08.05
고차함수(2) - Array.prototype.filter  (0) 2022.08.03
고차함수(1) - Array.prototype.map  (0) 2022.08.02
스프레드 문법  (0) 2022.08.02
템플릿 리터럴(ES6)  (0) 2022.07.30