[JS] 1. JS 데이터

Shy·2023년 9월 9일
0

NodeJS(Express&Next.js)

목록 보기
26/39

학습을 위한 초기 설정

terminal

npm을 설치하고 parcel을 설치한다.

npm init -y
npm i -D parcel

package.json

json 파일은 아래와 같이 한다.

{
  "name": "js",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "dev": "parcel ./index.html",
    "build": "parcel build./index.html"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "devDependencies": {
    "parcel": "^2.9.3"
  }
}

scripts 필드 내에 있는 dev와 build는 npm (또는 Yarn) 스크립트이다. 이 스크립트는 특정 명령어를 단순화하여 개발자가 패키지 관리 도구를 통해 쉽게 실행할 수 있도록 한다. 주어진 package.json에서는 parcel이라는 빌드 도구를 사용하고 있다.

  1. dev

    • 명령어: parcel ./index.html
    • 이 명령어는 Parcel 번들러를 사용하여 index.html을 기준으로 개발 모드로 웹 애플리케이션을 시작한다. 개발 모드에서는, 소스 코드의 변화를 자동으로 감지하고, 변경 사항을 빠르게 반영한다. 이를 통해 개발자는 코드 변경 후 바로 결과를 브라우저에서 확인할 수 있게 된다.
  2. build

    • 명령어: parcel build ./index.html
    • 이 명령어는 Parcel 번들러를 사용하여 프로덕션용 버전의 애플리케이션을 생성한다. 결과물은 최적화되고, 불필요한 코드가 제거된 상태로, 실제 배포할 준비가 된 상태가 된다.
      즉, 개발 중에는 npm run dev (또는 yarn dev) 명령어를 사용하여 실시간으로 변경사항을 확인하고, 배포 준비를 할 때는 npm run build (또는 yarn build) 명령어를 사용하여 최적화된 애플리케이션을 생성한다.

index.html

index.html은 아래와 같이 한다.

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <script type="module" defer src="./main.js"></script>
</head>
<body>
    <h1>Hello world!</h1>
</body>
</html>

여기서 주요 속성들에 대한 설명이다.

  1. type="module"
  • 이 속성은 스크립트를 ECMAScript 모듈로서 불러오라는 의미이다. ECMAScript 모듈 (ESM)은 최근의 자바스크립트 버전에서 도입된 모듈 시스템이다. 이를 사용하면 import 및 export 구문을 사용하여 모듈 간의 의존성을 선언하고 관리할 수 있다.
  • 브라우저는 type="module"이 지정된 스크립트를 모듈로 처리하기 때문에, 해당 스크립트 안에서 ESM 문법을 사용할 수 있게 된다.
  1. defer
    defer 속성은 HTML 파싱이 완료된 후에 스크립트를 실행하도록 한다. 기본적으로 스크립트는 다운로드와 실행 도중 HTML 파싱을 차단한다. defer를 사용하면 스크립트 다운로드는 병렬적으로 진행되지만, 실행은 HTML 파싱이 완료된 후에 순서대로 실행된다.
    type="module"이 지정된 스크립트는 기본적으로 defer의 동작을 한다. 그러나 명시적으로 defer 속성을 추가하는 것은 좋은 습관이며, 의도를 명확하게 표현한다.

  2. src="./main.js"
    src 속성은 외부 자바스크립트 파일의 경로를 지정한다. 여기서는 현재 디렉토리에 위치한 main.js 파일을 불러오도록 지정되어 있다.
    이렇게 구성된 이유는 웹 페이지의 렌더링 성능과 사용자 경험을 최적화하기 위함다. defer 속성은 브라우저가 페이지의 내용을 먼저 표시하고, 자바스크립트는 나중에 실행되게 함으로써 사용자가 페이지를 빠르게 볼 수 있게 해준다.

이렇게 구성된 이유는 웹 페이지의 렌더링 성능과 사용자 경험을 최적화하기 위함이다. defer 속성은 브라우저가 페이지의 내용을 먼저 표시하고, 자바스크립트는 나중에 실행되게 함으로써 사용자가 페이지를 빠르게 볼 수 있게 해준다.

원시형 - String, Number

String

const string1 = "Hello";
const string2 = "World";
const string3 = `Hello`;

string1, string2처럼 선언은 개인 취향이지만, string3는 다음과 같이 활용이 가능하다.

const string3 = `Hello ${string1}?!`;
// 데이터를 가져와서 출력.
// 이것 처럼 빽틱 기호를 사용하여 문자를 만드는 것을 템플릿 리터럴이라 한다.
// '' ""과 같이 작은 따옴표와 큰 따옴표를 사용하여 만드는 것은 리터럴이라 한다.

리터럴(Literal)

리터럴은 데이터의 표현입니다. 코드상에서 값을 직접 나타내는 표현식을 의미한다.
JavaScript에서는 여러 유형의 리터럴이 있다.

  • 숫자 리터럴: 123, 3.14
  • 문자열 리터럴: 'Hello', "World"
  • 부울 리터럴: true, false
  • 객체 리터럴: { name: 'John', age: 30 }
  • 배열 리터럴: [1, 2, 3]
  • 정규 표현식 리터럴: /ab+c/

템플릿 리터럴(Template Literal)

ES6 (ECMAScript 2015)에서 도입된 새로운 문자열 표현 방식이다. 백틱( ) 문자로 둘러싸인 문자열을 사용하여 표현된다. 템플릿 리터럴은 문자열 내에 변수나 표현식을 쉽게 포함시킬 수 있게 해주며, 멀티라인 문자열을 간단하게 만들 수 있다.

템플릿 리터럴의 주요 특징

  1. 문자열 내장: ${expression} 형식을 사용하여 문자열 내에 직접 변수나 표현식을 삽입할 수 있다.
let name = "John";
console.log(`Hello, ${name}!`);  // 출력: "Hello, John!"
  1. 멀티라인 지원: 백틱 문자열 내에서는 줄 바꿈을 직접 사용할 수 있다.
console.log(`This is a
multi-line string!`);

템플릿 리터럴은 문자열 연결과 표현식 포함을 더욱 간편하게 만들어 준다. 전통적인 문자열 연결 방식과 비교하면, 코드의 가독성이 향상되며, 실수를 줄일 수 있다.

Number

NaN

const number = -123.1234
const p = .14

console.log(number + undefined) // NaN
console.log(p) // 0.14
console.log(typeof (number + undefined)) // number
console.log(typeof p) // number           

JavaScript에서 NaN은 "Not a Number"의 약자로, 숫자가 아닌 값을 나타낸다. NaN은 여러 가지 수학 연산의 결과로 나타날 수 있으며, 특별한 속성을 가진 부동 소수점 값다.

NaN의 특징

  1. 어떤 값과도 (자기 자신 포함) 동일하지 않습니다. 즉, NaN === NaN 또는 NaN == NaN은 모두 false이다.
  2. isNaN() 함수는 값을 NaN으로 테스트하기 위한 전역 함수이다.
  3. Number.isNaN() 함수는 값이 NaN인지 확인하는 좀 더 안정적인 방법이다. isNaN()와 달리 Number.isNaN()는 값을 숫자로 강제 변환하지 않는다.

NaN이 발생하는 일반적인 예

  1. 숫자가 아닌 문자열 또는 연산할 수 없는 값을 숫자로 변환할 때
parseInt("Hello") // NaN
  1. 0으로 나누기
0 / 0  // NaN
  1. 수학 연산에서 유효하지 않은 경우
Math.sqrt(-1)  // NaN
  1. 두 개의NaN값이 연살될 때
NaN + 5  // NaN

NaN 처리 방법

  • isNaN() 또는 Number.isNaN()을 사용하여 NaN을 확인한다.
  • 산술 연산 전에 값을 확인하여 NaN 결과를 피한다.
  • NaN 값을 다른 값으로 대체하여 연산을 계속할 수 있다.

마지막으로, NaN은 독특한 특성 때문에 코드에서 버그를 일으킬 수 있다. 따라서 코드에서 숫자 값을 처리할 때는 항상 주의 깊게 접근해야 한다.

덧셈이 이상하다?

const a = 0.1
const b = 0.2

console.log(a + b) // 0.30000000000000004가 출력된다.

이 현상은 JavaScript에서 숫자를 표현하는 방식인 부동 소수점 산술에서 일반적으로 발생하는 문제이다. JavaScript의 모든 숫자는 IEEE 754 부동 소수점 형식을 사용하여 배정밀도(double-precision)로 표현된다.

이 현상의 원인을 좀 더 구체적으로 설명하면 다음과 같다.

  1. 이진 표현: 컴퓨터는 숫자를 이진 형식(0과 1)으로 저장한다. 0.1 및 0.2와 같은 10진수는 이진 형식으로 정확하게 표현될 수 없다. 따라서 컴퓨터는 이 숫자들을 가능한 한 가장 가까운 값으로 근사화한다.

  2. 누적 오차: 위에서 언급한 이진 근사화로 인해 실제 연산 시에 오차가 누적될 수 있다. 0.1 + 0.2의 경우, 두 숫자 각각의 작은 오차가 더해져서 최종 결과에도 그 오차가 반영된다.

이 문제는 JavaScript에만 국한된 것이 아니라 많은 프로그래밍 언어와 시스템에서 발생하는 문제이다.

해결 방법은 다양한데, 일반적으로 정밀한 소수점 연산이 필요한 경우에는 다음과 같은 방법을 고려할 수 있다.

  1. 정수 연산: 소수점 연산을 정수 연산으로 변환합니다. 예를 들어, 0.1을 10으로, 0.2를 20으로 변환하여 연산한 다음, 결과를 100으로 나눠서 원하는 결과를 얻을 수 있다.
  2. 라이브러리 사용: decimal.js나 big.js와 같은 라이브러리를 사용하여 정밀한 소수점 연산을 수행할 수 있다.
  3. 아래와 같이 toFixed를 사용하여 반올림하여도 해결이 가능하다. 다만 이 메소드를 사용할 경우 타입이 문자열이 된다.
const a = 0.1
const b = 0.2

console.log((a + b).toFixed(1)) // 0.3
console.log(typeof (a + b).toFixed(1)) // string

원시형 - Boolean, null, undefined

Boolean

const a = true
const b = false

let isTrue = Boolean(1); // true
let isFalse = Boolean(0); // false

이 타입은 주로 조건문, 논리 연산자, 비교 연산자의 결과로 사용되며, 코드의 조건부 실행에 주로 활용된다.

Falsy (거짓 같은) 값

JavaScript에서는 false가 아닌 몇몇 특정 값들이 조건문에서 false처럼 동작한다. 이러한 값을 "falsy" 값이라고 한다

  1. false
  2. 0 (숫자 0)
  3. '' 또는 "" (빈 문자열)
  4. null
  5. undefined
  6. NaN

논리 연산자

Boolean 값을 사용할 때 자주 사용되는 논리 연산자에는 && (AND), || (OR), 그리고 ! (NOT)이 있다.

null

JavaScript에서 null은 특별한 값으로, 어떤 변수가 의도적으로 값이 없음을 나타내고 싶을 때 사용된다. 다음은 null에 대한 몇 가지 중요한 특성과 특징이다.

  1. 의도적인 부재: null은 "값이 없음" 또는 "알 수 없음"을 의미한다. 어떤 변수가 아무런 값도 가지고 있지 않다는 것을 명시적으로 나타내고자 할 때 null을 사용한다.
  2. 원시 값: null은 원시 값(primitive value)입니다. 이것은 객체나 함수 등이 아닌, 단순한 값이라는 것을 의미한다.
  3. 타입: JavaScript에서 typeof 연산자를 사용하여 null의 타입을 확인하면 이상하게도 "object"를 반환한다. 이것은 JavaScript의 초기 버전에서의 버그 때문인데, 이 버그는 하위 호환성 문제로 인해 수정되지 않았다.
console.log(typeof null); // "object"
  1. 비교: null은 undefined와 비슷하게 동작하며, 두 값은 == (추상 동등 비교)를 사용하여 서로 비교하면 true를 반환하지만, === (일치 비교)를 사용하면 false를 반환한다.
console.log(null == undefined);  // true
console.log(null === undefined); // false
  1. 변수 초기화: 변수를 초기화하면서 의도적으로 값을 설정하지 않고자 할 때 null을 사용한다.
let data = null;
  1. 객체 속성의 부재: 객체의 특정 속성이 없음을 명시적으로 표시하고자 할 때 null을 사용할 수 있다.
let person = {
  name: 'John',
  age: null // 나이 정보가 없음을 나타냄
};

요약하면, null은 JavaScript에서 의도적으로 값을 부재하게 만들고 싶을 때 사용하는 특별한 원시 값이다.

undefined

JavaScript에서 undefined는 변수가 선언되었으나 아직 값이 할당되지 않았을 때의 기본값이다. undefined에 대한 몇 가지 중요한 특성과 특징은 다음과 같다.

  1. 변수의 초기 값: JavaScript에서 새로운 변수를 선언하고 값을 할당하지 않으면, 그 변수의 값은 undefined이다.
let myVar;
console.log(myVar); // undefined
  1. 원시 값: undefined도 JavaScript의 원시 값(primitive value) 중 하나이다.
  2. 타입: undefined의 타입은 "undefined"입니다. 이것은 typeof 연산자를 사용하여 확인할 수 있다.
console.log(typeof undefined); // "undefined"
  1. 함수의 반환 값이 없을 때: 함수에서 명시적으로 값을 반환하지 않으면, 그 함수는 undefined를 반환한다.
function noReturnValue() {}
console.log(noReturnValue()); // undefined
  1. 존재하지 않는 객체 속성: 객체에 존재하지 않는 속성에 접근하려고 하면, undefined를 반환한다.
let obj = {};
console.log(obj.nonexistentProperty); // undefined
  1. 명시적으로 사용하기: 개발자는 변수에 명시적으로 undefined 값을 할당할 수 있다. 그러나 이것은 좋은 습관이 아니다. 값이 없음을 나타내려면 null을 사용하는 것이 더 좋다.
  2. 비교: undefined는 null과 비슷하게 동작하며, 두 값은 == (추상 동등 비교)를 사용하여 서로 비교하면 true를 반환하지만, === (일치 비교)를 사용하면 false를 반환한다.
console.log(undefined == null);  // true
console.log(undefined === null); // false

요약하면, undefined는 값이 아직 할당되지 않은 변수나 존재하지 않는 객체의 속성, 반환 값이 없는 함수의 반환 값 등에서 발생하는 특별한 원시 값이다.

예제

const user = {
  name: 'HEROPY',
  age: 85
}

console.log(user.name) // HEROPY
console.log(user.age) // 85
console.log(user.email) // undefined

참조형 - Array

JavaScript의 Array는 순서가 있는 값들의 컬렉션이다. 배열은 객체의 일종이며, 인덱스로 값에 접근할 수 있다. 배열은 다양한 자료형의 요소를 포함할 수 있으며, 배열의 크기는 동적으로 변경될 수 있다.

배열의 주요 특징

  1. 동적 크기: 배열은 고정된 크기가 아니며, 동적으로 크기가 조정된다.
  2. 다양한 자료형의 요소: 배열은 문자열, 숫자, 객체, 함수, 다른 배열 등 어떤 타입의 요소(Element, item)도 포함할 수 있다.
  3. 순서가 유지: 배열의 요소는 추가된 순서대로 유지된다.

배열의 생성

  1. 배열 리터럴: 가장 일반적인 방법은 대괄호 []를 사용하는 것이다.
let fruits = ['apple', 'banana', 'cherry'];
  1. Array 생성자: new키워드와 함께 Array 생성자를 사용하여 배열을 만들 수도 있다. 조금 불편하므로, 배열 리터럴로 하는 것이 좋다.
let fruits = new Array('apple', 'banana', 'cherry');

배열의 메소드 및 속성

  1. length: 배열의 길이(요소의 개수)를 나타낸다.
console.log(fruits.length); // 3
  1. push & pop: 배열의 끝에 요소를 추가하거나 제거한다.
fruits.push('date');   // 'apple', 'banana', 'cherry', 'date'
fruits.pop();          // 'apple', 'banana', 'cherry'
  1. shift & unshift: 배열의 시작 부분에 요소를 추가하거나 제거한다.
fruits.unshift('mango'); // 'mango', 'apple', 'banana', 'cherry'
fruits.shift();          // 'apple', 'banana', 'cherry'
  1. forEach, map, filter, reduce: 배열 요소에 대한 반복 및 연산을 위한 고차 함수이다.
  2. splice: 배열에서 요소를 추가하거나 제거한다.
fruits.splice(1, 0, 'kiwi');  // 1번 인덱스에 'kiwi' 추가

let months = ["January", "February", "Monday", "Tuesday"];
let days = months.splice(2, 2, "March", "April"); // 요소 두 개를 제외하고, 다른 요소를 추가
console.log(days); // ["Monday", "Tuesday"]
console.log(months); // ["January", "February", "March", "April"]
  1. indexOf & includes: 배열에서 요소의 인덱스를 찾거나 요소의 존재 여부를 확인한다.
  2. join & split: 배열의 요소를 문자열로 결합하거나 문자열을 배열로 분할한다.

배열은 자바스크립트에서 매우 중요한 데이터 구조로, 많은 작업과 연산을 간단하게 만들어 준다. 배열과 관련된 메서드는 자주 사용되므로, 다양한 메서드들을 익숙하게 사용하는 것이 좋다.

참조형 - Object

JavaScript에서 Object는 키와 값의 쌍으로 구성된 데이터 구조를 나타낸다. 객체는 데이터와 함께 그 데이터를 처리하는 메서드를 캡슐화하는 데 사용된다. Object는 자바스크립트에서 참조 타입이다, 즉 변수에 객체가 저장될 때 실제 객체의 데이터가 아닌 객체에 대한 참조가 저장된다.

객체의 주요 특징

  1. 키와 값의 쌍: 객체는 키(key)와 값(value)의 쌍으로 구성된다. 키는 문자열 또는 심볼이어야 하며, 값은 어떠한 타입이든 될 수 있다.

  2. 동적 속성: 객체의 속성은 동적으로 추가하거나 제거할 수 있다.

  3. 메서드: 객체는 함수를 값으로 포함할 수 있다. 이러한 함수를 객체의 메서드라고 한다.

객체의 생성 및 사용

  1. 객체 리터럴: 가장 일반적인 방법은 중괄호 {}를 사용하는 것이다.
const person = {
    firstName: 'John',
    lastName: 'Doe',
    age: 30,
    greet: function() {
        console.log('Hello, ' + this.firstName);
    }
};
  1. Object 생성자: new 키워드와 함께 Object 생성자를 사용하여 객체를 만들 수도 있다.
const person = new Object();
person.firstName = 'John';
person.lastName = 'Doe';
  1. 생성자 함수: 사용자 정의 생성자 함수를 사용하여 여러 객체를 생성할 수 있다.
function Person(firstName, lastName) {
    this.firstName = firstName;
    this.lastName = lastName;
}

const john = new Person('John', 'Doe');

객체의 속성 및 메서드에 접근

  1. 점 표기법
console.log(person.firstName); // John
  1. 대괄호 표기법: 변수나 동적으로 속성 이름을 가져오려 할 때 사용한다.
const keyName = 'lastName';
console.log(person[keyName]); // Doe
console.log(person[lastName]); // Doe
  1. 메서드 호출
person.greet(); // Hello, John

중첩된 객체(Nested Object)

const userA = {
  name: 'HEROPY',
  age: 85
}
const userB = {
  name: 'Neo',
  age: 22,
  parent: userA
}

const users = [userA, userB]

console.log(userB.parent.name) // HEROPY
console.log(users[0]['name']) // Heropy

프로토타입

모든 자바스크립트 객체는 프로토타입이라는 다른 객체에 대한 내부 링크를 갖는다. 프로토타입은 객체의 상속을 가능하게 하며, 프로토타입 체인을 통해 객체는 그것의 프로토타입에서 메서드와 속성을 상속받을 수 있다.

객체는 자바스크립트에서 중요한 데이터 구조로서, 복잡한 애플리케이션에서 데이터 모델링 및 로직 캡슐화에 매우 유용하다.

참조형 - Function

avaScript에서 Function도 객체로 취급된다. 함수는 특별한 종류의 객체이며, 실행 가능한 코드를 포함하고 있다. 함수는 일급 객체(first-class object)의 특성을 가지기 때문에 다른 값들처럼 변수에 할당하거나, 객체의 프로퍼티로 사용하거나, 배열의 요소로 저장하거나, 다른 함수의 인수로 전달하거나 리턴값으로 사용할 수 있다.

함수의 주요 특징

  1. 호출 가능: 함수는 ()를 사용하여 호출할 수 있다. 호출 시 함수 내부의 코드가 실행된다.

  2. 변수 환경: 함수는 자신만의 변수 환경을 갖는다. 이를 통해 함수는 클로저를 형성하며 외부 스코프의 변수에 접근할 수 있다.

  3. 매개변수: 함수는 인수를 받아들일 수 있다. 이 인수들은 함수 내부에서 사용될 수 있다.

  4. 리턴 값: 함수는 값을 반환할 수 있다. 반환하지 않으면, 기본적으로 undefined를 반환한다.

함수 생성 방법

  1. 함수 선언식(Function Declaration)
function greet(name) {
    console.log('Hello, ' + name);
}
  1. 함수 표현식(Function Expression)
const greet = function(name) {
    console.log('Hello, ' + name);
};
  1. 화살표 함수(Arrow Function)
const greet = name => console.log('Hello, ' + name);

함수 불러오기

function hello() {
  console.log('Hello!')
}

hello() // Call

위처럼 함수를 불러오는 것을 함수를 콜한다고 한다.

기타 함수의 특성

  1. 생성자 함수: new 키워드와 함께 호출될 수 있으며, 객체를 생성하고 초기화한다.

  2. 익명 함수: 이름이 없는 함수로, 주로 콜백 함수나 한 번만 사용될 함수로 사용된다.

  3. 즉시 실행 함수(IIFE, Immediately Invoked Function Expression): 정의와 동시에 실행되는 함수이다.

프로토타입

Function도 객체이기 때문에 프로토타입 속성을 갖는다. 이는 함수의 메서드 및 속성을 확장할 때 유용하다.

메서드

함수 객체는 호출(call), 바인드(bind), 적용(apply)과 같은 여러 내장 메서드를 갖는다. 이 메서드들은 함수의 컨텍스트를 조작하거나 인수를 전달하는 방식에 따라 함수를 호출할 때 유용하다.

함수는 JavaScript에서 매우 중요한 구성 요소로, 그 자체로 실행 가능한 코드 블록을 캡슐화한다. 이는 코드의 재사용성과 구조화를 촉진하며, 고차 함수와 클로저와 같은 고급 프로그래밍 패턴의 구현을 가능하게 한다.

형 변환(Type Conversion)

자바스크립트에서 형 변환(Type Conversion) 또는 타입 캐스팅(Type Casting)은 한 데이터 타입을 다른 데이터 타입으로 변환하는 과정이다. 이러한 변환은 때때로 프로그래머에 의해 명시적으로 수행되기도 하며, 때로는 자바스크립트 엔진에 의해 암시적으로 수행된다.

  1. 암시적 형 변환 (Implicit Type Conversion)
    이는 자바스크립트 엔진이 코드의 맥락을 기반으로 자동으로 데이터 타입을 변환하는 경우이다.
let result = '5' + 7; // '57' (문자열로 변환)
  1. 명시적 형 변환 (Explicit Type Conversion)
    프로그래머가 의도적으로 특정 함수나 연산자를 사용하여 데이터 타입을 변환하는 경우이다.
let number = Number('5'); // 5 (숫자로 변환)

주요 형 변환 방법

  1. 문자열로 변환
    • String(value) 함수를 사용하거나
    • value.toString() 메서드를 사용한다.
let val = String(123); // "123"
let val2 = (123).toString(); // "123"
  1. 숫자로 변환
    • Number(value) 함수를 사용하거나
    • 단항 연산자 +를 사용한다.
let num = Number('123'); // 123
let num2 = +'123'; // 123
  1. 불리언으로 변환
    • Boolean(value) 함수를 사용하거나
    • 두 번의 NOT 연산자 !!를 사용한다.
let bool = Boolean(1); // true
let bool2 = !!1; // true

암시적 변환의 특징

  1. 문자열 연결
    숫자와 문자열을 더할 때, 숫자는 문자열로 변환된다.
'Hello' + 5 // "Hello5"
  1. 산술 연산
    문자열을 숫자로 암시적으로 변환하여 연산한다. 하지만 덧셈을 제외한 다른 연산자(-, *, /, % 등)를 사용할 때이다.
'5' - 3 // 2
'5' * '2' // 10
  1. 비교 연산
    == (동등 연산자)를 사용하여 비교할 때 암시적 변환이 발생할 수 있다. 그러나 === (일치 연산자)를 사용하면 형 변환이 발생하지 않는다.
'5' == 5 // true
'5' === 5 // false

형 변환은 자바스크립트에서 자주 발생하는 현상이며, 특히 암시적 변환은 예기치 않은 결과를 초래할 수 있기 때문에 주의해야 한다. 프로그래밍을 할 때 항상 데이터 타입을 고려하고 필요에 따라 명시적으로 형 변환을 수행하는 것이 좋다.

참과 거짓(Truthy & Falsy)

자바스크립트에서는 특정 값들이 불리언(Boolean) 컨텍스트에서 평가될 때 그 값들이 true 또는 false로 간주되는 것을 의미하는 "Truthy"와 "Falsy"라는 용어를 사용한다.

Falsy 값

Falsy 값은 불리언 컨텍스트에서 false로 평가되는 값을 의미한다. 자바스크립트에서 다음은 Falsy 값의 목록이다

  1. false - 불리언의 false 값 자체.
  2. 0 - 숫자 0.
  3. "" 또는 '' (빈 문자열) - 길이가 0인 문자열.
  4. null - null 값.
  5. undefined - undefined 값.
  6. NaN - "Not a Number"를 나타내는 특수한 숫자 값.

Truthy 값

Falsy 값들을 제외한 모든 값은 불리언 컨텍스트에서 true로 간주되며, 이러한 값들을 Truthy라고 합니다. 몇 가지 예는 다음과 같다.

  1. 모든 숫자 (0과 NaN 제외)
  2. 모든 문자열 ("" 빈 문자열 제외)
  3. 모든 객체, 배열, 함수 (빈 객체와 배열도 포함)
  4. true - 불리언의 true 값 자체.

예시

if ([]) {
    console.log('This will be printed because an empty array is truthy.');
}

이러한 Truthy와 Falsy 개념은 조건문, 삼항 연산자, 논리 연산자(&&, ||, ! 등) 등 다양한 곳에서 유용하게 사용된다.

데이터 타입 확인

JavaScript에서 데이터의 타입을 확인하는 방법은 주로 typeof 연산자를 사용한다. 또한, 더 복잡한 자료구조나 인스턴스의 타입을 확인하고자 할 때는 instanceof 연산자를 사용할 수 있다.

typeof 연산자

typeof는 주어진 값의 타입을 문자열로 반환한다.

console.log(typeof 123);         // "number"
console.log(typeof 'hello');     // "string"
console.log(typeof true);        // "boolean"
console.log(typeof undefined);   // "undefined"
console.log(typeof function(){}); // "function"
console.log(typeof {});          // "object"
console.log(typeof []);          // "object"
console.log(typeof null);        // "object" (이것은 JavaScript의 오래된 버그로 간주된다)

instanceof 연산자

instanceof 연산자는 주어진 객체가 특정 생성자의 인스턴스인지 확인하는데 사용된다.

console.log([] instanceof Array);         // true
console.log({} instanceof Object);       // true
console.log('hello' instanceof String);  // false (문자열 원시값은 String 객체의 인스턴스가 아니다)
console.log(new String('hello') instanceof String); // true

Object.prototype.toString.call()

typeof나 instanceof로 충분한 정보를 얻지 못할 때, Object.prototype.toString.call() 메서드를 사용하여 정확한 타입을 얻을 수 있다.

console.log(Object.prototype.toString.call([]));    // "[object Array]"
console.log(Object.prototype.toString.call({}));    // "[object Object]"
console.log(Object.prototype.toString.call(null));   // "[object Null]"
console.log(Object.prototype.toString.call(undefined)); // "[object Undefined]"

이 방법은 null, undefined, array 등의 정확한 타입을 판별하는 데 유용하다.

각 방법은 특정 상황에 따라 적합하므로 필요에 따라 적절한 방법을 선택하여 사용하면 된다.

constructor

객체가 생성될 때, 그 객체의 원형(프로토타입)에는 constructor 프로퍼티가 있어 해당 객체의 생성자 함수를 가리킨다. 기본 내장 객체들, 예를 들어 Array, Object, String, Number 등도 이 규칙을 따른다.

const arr = [];
console.log(arr.constructor === Array);  // true

const obj = {};
console.log(obj.constructor === Object);  // true

const str = "hello";
console.log(str.constructor === String);  // true

const num = 123;
console.log(num.constructor === Number);  // true

그러나 constructor를 사용하여 타입을 검사하는 것은 몇 가지 주의점이 있다.

  1. 상속된 객체의 경우 원래 객체의 생성자를 가리킬 수 있다.
  2. 객체의 constructor 프로퍼티가 수정될 수 있다.
  3. null과 undefined는 constructor 프로퍼티가 없다.

따라서, 대부분의 경우 typeof 연산자나 instanceof 연산자, 그리고 Array.isArray()와 같은 몇몇 내장 메서드들이 타입 검사에 더 일반적으로 사용된다.

profile
초보개발자. 백엔드 지망. 2024년 9월 취업 예정

0개의 댓글