본문 바로가기
Front-End, CS 스터디/항해99 - JavaScript 스터디

[자바스크립트 JavaScript] 느슨한 타입의 동적 언어

by 제니운 2022. 7. 16.
728x90

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

 

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

 

1️⃣ 동적 타입

 

JavaScript는 느슨한 타입(loosely typed)의 동적(dynamic) 언어입니다. JavaScript의 변수는 어떤 특정 타입과 연결되지 않으며, 모든 타입의 값으로 할당 (및 재할당) 가능합니다.

 

(예시)

let foo = 42 // foo가 숫자
foo = 'bar' // foo가 이제 문자열
foo = true // foo가 이제 불리언

"모든 타입의 값"으로 할당 및 재할당이 가능하다는 말은 예시처럼 숫자의 타입으로도, 문자열로도, 불리언으로도 할당할 수 있다는 의미!

 

* 불리언 : true, false 참 거짓 

 

2️⃣ JavaScript의 타입

 

[원시 값] 과 [객체]로 나뉜다.

 

👌 원시 값 : 언어의 최고 로우레벨에서 직접 표현되는 불변 데이터, 객체를 제외한 모든 타입은 불변 값(변경할 수 없는 값)을 정의한다. 예를 들어 (C언어와는 달리) 문자열은 불변한다. 이런 일련의 타입을 "원시 값"이라 한다.

 

1) Boolean 타입 : 논리 요소, true와 false 두 가지의 값

 

- 불린 : 논리적인 데이터 유형, 참(true) 혹은 거짓(false) 값만을 가질 수 있다. 불린 조건은 코드 부문이 실행되어야 할지(예를 들어, if 절 안에서) 또는 어떤 코드 부문을 반복해야 할지(예를 들어 for문 안에서) 결정하는데 쓰인다.

 

- Boolean : Boolean 객체는 불리언 값을 감싸고 있는 객체

 

🔹 false : 0, -0, null, false, NaN, undefined, 빈 문자열 ("") 이라면 객체의 초기값은 false 가 된다.

🔹 true : undefined, null 이 아닌 모든 객체는 조건문에서 true 로 계산된다.이는 값이 false 인 Boolean 객체도 포함된다.

 

var x = new Boolean(false);
if (x) {
  // 이 코드는 실행됨
}

원시 Boolean 값에는 적용되지 않는다.

var x = false;
if (x) {
  // 이 코드는 실행되지 않음
}

불리언이 아닌 값을 변환할 때 Boolean 객체를 사용해선 안된다. Boolean 함수를 사용할 것

Boolena() : Boolean 객체를 생성한다.

var x = Boolean(expression);     // 추천
var x = new Boolean(expression); // 사용하지 말것

 

2) Null 타입 : null 하나의 값만 가질 수 있다.

 

- Null : 컴퓨터 과학에서 null 값은 일반적으로 존재하지 않거나, 유효하지 않은 object 또는 주소를 의도적으로 가리키는 참조를 나타낸다. null 참조의 의미는 언어의 구현에 따라 다양하다. null은 동작이 원시적으로 보이기 때문에 primitive values(원시 값) 중 하나로 표시된다.

 

특정 경우엔, null 은 원시적이지 않다. 모든 객체는 null 값으로 부터 파생되며 따라서 typeof 연산자는 아래의 코드에서 object를 반환한다. 

 

typeof null === 'object' // true

- null : 자바스크립트의 원시 값 중 하나, 어떤 값이 의도적으로 비어있음을 표현하며 연산에서는 거짓으로 취급한다.

 

 

3) Undefined 타입 : 선언한 후 값을 할당하지 않은 변수, 혹은 값이 주어지지 않은 인수에 자동으로 할당

 

var x; // 값을 할당하지 않고 변수 선언

console.log("x's value is", x) // "x's value is undefined" 출력

 

4) Number 타입 : ECMAScript 는 Number 와 BigInt 두 가지의 내장 숫자 타입을 가지고 있다.

 

- 배정밀도 64비트 이진 형식 IEEE 754값 (-(2^53 -1)부터 2^53 -1 까지의 수)

- 부동 소수점 숫자 외에도 +Infinity, -Infinity, NaN("Not a Number") 세 개의 상징적인 값을 가진다.

 

=> ±Infinity 범위 내에서 가장 크거나 작은 수 확인하려면 : Number .MAX VALUE 와 Number .MIN VALUE 상수를 사용할 수 있다.

 

- Number 타입의 값 중 두 가지 형식으로 표현할 수 있는 유일한 값 : +0, -0(0은 +0의 별칭)

이 사실이 영향을 주는 것은 거의 없다. 예를 들어, +0 === -0 은 참이다. 그러나, 0으로 나눌 경우 둘의 차이가 발생된다.

 

> 42 / +0
Infinity
> 42 / -0
-Infinity

 

 

5) BigInt 타입 : 정수를 나타낼 수 있는 JavaScript 숫자 원시 값

 

- 정수 끝에 n을 추가하거나, 생성자를 호출해 생성할 수 있다.

 

- Number의 안전 한계를 넘어서는 큰 정수도 안전하게 저장하고 연산할 수 있다.

* Number의 안전 한계 : Number .MAX SAFE INTEGER 로 알아볼 수 있다. BigInt의 도입 이후로는 이 한계를 넘는 숫자에 대해 계산이 가능하다.

 

 

아래와 같이, Number . MAX_SAFE_INTEGER 밖으로 나가는 정수에서도 예상된 값을 반환하는 것을 보인다.

 

> const x = 2n ** 53n;
9007199254740992n
> const y = x + 1n;
9007199254740993n

 

- +, *, -, **, % 연산자를 Number에 사용하듯 BigInt에서도 사용할 수 있다. BigInt는 Number와 엄격하게 같지는 않으나 유사하다.

 

- if, ||, &&, Boolean, ! 처럼 불리언 변환히 발생하는 곳에서는 Number 처럼 동작한다.

 

- Number와 혼합해 연산할 수 없으며, 이 때 TypeError가 발생한다.

 

 

6) String 타입 : 텍스트 데이터를 나타낼 때 사용한다. 16비트 부호 없는 정수 값 "요소"로 구성된 집합으로, 각각의 요소가 String의 한 자리를 차지한다.

 

- 첫 번째 요소는 인덱스 0에, 그 다음 요소는 1, 2 ,,, String의 길이는 그 안의 요소 수와 같다.

 

- JavaScript의 문자열은 불변한다(C언어와 달리). 즉, 문자열을 생성한 후 바꾸는 것은 불가능하다. 그러나, 원본 문자열을 사용해서 새로운 문자열을 생성하는 것은 가능하다.

 

예를 들어 아래처럼, 각각의 문자를 선택하거나 부분 문자열이거나, 연결 연산자 +를 사용한 경우

 

  • 원본 문자열에서 각각의 문자를 선택하거나 String.substr()을 사용해 생성한 부분문자열
  • 연결 연산자(+)를 사용하거나 String.concat()을 사용해 두 개의 문자열을 합친 결과물

 

 

7) Symbol 타입 : 고유하고 변경 불가능한 원시 값, 객체의 속성, 객체의 속성 키로 사용할 수 있다.

* 어떤 프로그래밍 언어들에선 "아톰"이라고 부르기도 한다.

 

- 새 원시(privitive) 심볼을 생성하려면, 심볼을 설명하는 선택적(optional)문자열과 함께 Symbol()을 쓰면 된다.

 

var sym1 = Symbol();
var sym2 = Symbol("foo");
var sym3 = Symbol("foo");

 

위의 코드는 세 개의 새 심볼을 생성한다. Symbol("foo")는 "foo"라는 문자열을 심볼로 강제로 변환시키 않는다는 점에 유의해야 한다. 해당 코드는 매 번 새로운 심볼을 생성한다.

 

Symbol("foo") === Symbol("foo"); // false

 

new 연산자를 이용한 문법은 TypeError를 발생시킨다.

 

var sym = new Symbol(); // TypeError

 

이는 작성자가 새로운 심볼 값 대신 명시적으로 심볼 래퍼 객체(Symbol wrapper object)를 생성할 수 없게 한다. 일반적으로 원시 데이터 형에 대한 명시적인 래퍼 객체 형성(예를 들어, new Boolean, new String 또는 new Number 와 같은)이 가능하다는 점에 비춰보면 의외일 수 있다.

 

꼭 심볼 래퍼 객체를 생성하고 싶다면, object() 함수를 이용할 수 있다.

 

var sym = Symbol("foo");
typeof sym;     // "symbol"
var symObj = Object(sym);
typeof symObj;  // "object"

 

👌 객체 : 속성의 컬렉션, 컴퓨터 과학에서의 객체란 식별자로 참조할 수 있는 메모리 상의 값을 말한다.

 

- 객체 리터럴 구문을 사용해 제한적으로 속성을 초기화 할 수 있고 그 후에 속성을 추가하거나 제거할 수도 있다.

 

* 객체 리터럴 구문 : ({}) 중괄호로 묶인 0개 이상인 객체의 속성명과 관련 값 쌍 목록

// 주의 : 문(statement)의 시작에 객체 리터럴을 사용해서는 안된다. 이는 { 가 블록의 시작으로 해석되기 때문에 오류를 유발하거나 의도한대로 동작하지 않기 떄문

 

 

car의 객체의 첫째 요소는 myCar 속성을 정의하고 문자열 "Saturn"을 할당한다.

둘째 요소인 getCar 속성은 함수 (car(Types("Honda"))를 호출한 결과가 즉시 할당된다.

셋째 요소 special 속성은 기존 변수 (sales)를 사용한다.

var sales = 'Toyota';

function carTypes(name) {
  if (name === 'Honda') {
    return name;
  } else {
    return "Sorry, we don't sell " + name + ".";
  }
}

var car = { myCar: 'Saturn', getCar: carTypes('Honda'), special: sales };

console.log(car.myCar);   // Saturn
console.log(car.getCar);  // Honda
console.log(car.special); // Toyota

 

게다가, 속성명으로 숫자나 문자열 리터럴을 사용하거나 또 다른 객체 리터럴 내부에 객체를 중첩할 수도 있다.

 

var car = { manyCars: {a: 'Saab', b: 'Jeep'}, 7: 'Mazda' };

console.log(car.manyCars.b); // Jeep
console.log(car[7]); // Mazda

 

객체 속성명은 빈 문자열 포함 어떤 문자열도 될 수 있다. 속성명이 유효한 JavaScript 식별자나 숫자가 아닌 경우, 따옴표로 묶여야 한다.

 

또한, 유효한 식별자가 아닌 속성명은 점(.) 속성으로 접근할 수 없다. 대신 배열 같은 표기법 ("[]")으로 접근하고 값을 설정할 수 있다.

 

var unusualPropertyNames = {
  '': 'An empty string',
  '!': 'Bang!'
}
console.log(unusualPropertyNames.'');   // SyntaxError: Unexpected string
console.log(unusualPropertyNames['']);  // An empty string
console.log(unusualPropertyNames.!);    // SyntaxError: Unexpected token !
console.log(unusualPropertyNames['!']); // Bang!

 

728x90