본문 바로가기
  • soldonii's devlog
Javascript 공부/Advanced Javascript(-)

자바스크립트의 데이터 타입

by soldonii 2019. 9. 9.

*Udemy의 "Advanced Javascript Concepts"강의에서 학습한 내용을 정리한 포스팅입니다.

*자바스크립트를 배우는 단계라 오류가 있을 수 있습니다. 틀린 내용은 댓글로 말씀해주시면 수정하겠습니다. 감사합니다. :)


1. 자바스크립트의 데이터 타입

자바스크립트의 데이터 타입은 총 7개이다. number, booleans, strings, undefined, null, Symbol, object이다.

 

# undefined vs. null

- undefined : abscence of definition, 정의가 되지 않은 것, 즉 어떠한 값이 할당되지 않은 것이다.

- null : abscence of value, 값은 정의가 되어 있지만, 해당 값이 비어있는 값인 경우이다.

 

# 배열과 함수는 객체에 포함된 개념

Object {} 안에 Array []와 Function ()이 포함되어 있는 개념이다. 즉, 배열과 함수는 객체에 포함되어 있는 개념이다.

 

# Primitive vs. Non-Primitive

- primitive : 자바스크립트에서 객체를 제외한 모든 데이터 타입은 primitive이다. primitive란 메모리 공간에 단 한 개의 값만을 가지고 있는 데이터를 의미한다. 원자와 같은 개념으로, 더 이상 작은 단위로 데이터가 쪼개질 수가 없다. 예를 들어 let number = 5; 라는 코드의 경우, number의 값이 저장되어 있는 메모리 공간에는 딱 5 이외의 어떤 데이터도 없으며, 5는 더 이상 작은 단위로 쪼개질 수 없다.

- non-primitive : 객체(배열, 함수 포함)는 non-primitive로, 메모리에 직접적으로 값을 보관하지 않고 대신 주소를 referencing하고 있다.

 

참고로 number, string같은 데이터 타입도 사실은 더 큰 범위에서는 거대한 Number, String과 같은 객체로 둘러 쌓여 있는 존재이다. 

true.toString(); // 'true'
Boolean(true).toString(); // 'true'

 

true라는 boolean 값에 toString이라는 메소드를 사용했다. 메소드를 사용했다는 것 자체가, 이미 true라는 값이 객체라는 것을 의미한다. 

 

2. 함수도 객체의 일부

실행 컨텍스트 내부

 

# 생성자 함수

함수를 생성하고 호출하는데에 1) ()(일반적인 함수 호출), 2) .call(), .apply(), .bind() 외에도 new 키워드를 사용할 수 있다.

const four = new Function('num, ''return num');
four(4);

 

위 코드는 변수 four에 num을 매개변수로 받아서 num을 return하는 함수를 생성하게 된다. 여기서 Function은 함수를 생성하는 생성자 함수이다. 

 

# 함수는 객체이다?

function woohooo() {
  console.log('woohooo~');
}
woohooo.yell = 'ahahhhh';

 

위 코드로 woohooo라는 이름을 가진 함수를 생성한 뒤, woohooo 함수에 dot notation을 이용해서 yell 프로퍼티에 값을 추가했다. dot notation으로 값을 추가했다는 것은 함수가 객체라는 것의 증거가 된다. 

이처럼 자바스크립트에서 함수를 선업하면 callable object가 생성된다. 정확히 동일한 것은 아니지만, 위 코드는 아래의 특별한 객체를 생성하는 행위와 유사하다.

 

const specialObj = {
  yell: 'ahahhhh',
  name: 'woohooo', // function의 이름
  (): console.log('woohooo~')
};

 

함수가 객체라는 것의 진짜 의미는, 함수를 단순히 특정 동작을 수행토록하는 수단이 아니라, 하나의 데이터를 저장하고 있는 데이터 저장소처럼 다룰 수 있다는 의미이다.

# First Class Citizen

함수가 객체라는 것을 달리 말하면, 함수는 First Class Citizen이라는 의미이다. 무슨 뜻일까?

 

1) 함수는 변수에 저장되거나 객체의 프로퍼티로 지정될 수 있다.

2) 하나의 함수를 또 다른 함수의 인자로 전달할 수 있다.

3) 다른 함수의 리턴 값으로 함수를 전달할 수 있다.

// 1. 변수에 저장될 수 있는 함수
var stuff = function () {}
// 2. 함수 안에 인자로 다른 함수를 전달
function a(fn) {
  fn();
}
// 3. 함수의 리턴값으로 함수를 리턴
function b() {
  return function c() {console.log('bye');}
}

 

함수가 일급 객체(First Class Citizen)라는 개념으로 인해 자바스크립트의 프로그래밍 패턴으로 Functional Programming(함수형 프로그래밍)이라는 패턴이 생겨날 수 있게 되었다. (이 개념은 추후 강의에서 공부해본다.)

 

# 고차함수(Higher Order Function)

자바스크립트에서 함수가 일급 객체라는 것은, 곧 함수를 다른 함수의 인자로 전달하거나, 함수의 리턴 값으로 다른 함수를 리턴시킬 수 있다는 의미라고 했다. 그렇기 때문에 자바스크립트에서 함수는 곧 고차함수(Higher Order Function)로 활용하는 것도 가능하다.

(고차함수 : 다른 함수를 인자로 받는 함수 또는 다른 함수를 리턴시키는 함수를 의미한다.)

고차함수는 왜 유용할까??

 

1) 일반적인 함수 : function()

function letAdamLogin() {
  let array = [];
  for (let i = 0; i < 1000000; i++) {
    array.push(i);
  }
  return 'Access Granted to Adam';
}

function letEvaLogin() {
  let array = [];
  for (let i = 0; i < 1000000; i++) {
    array.push(i);
  }
  return 'Access Granted to Eva';
}

letAdamLogin();
letEvaLogin();

 

위 사례는 특정 사용자가 로그인을 할 때, 길이가 10만인 배열을 돈 후에 Access Granted to User와 같은 메시지를 리턴시켜 로그인되도록 하는 함수이다. 위 사례만 봤을 때는 문제가 없어 보이지만, 만약 이용자가 1억명이라면? 그 때마다 함수 안의 코드들을 복사해서 새로운 함수를 만들 것인가? 

결론적으로, 일반적인 함수만을 사용할 경우 DRY(Do not Repeat Yourself) 문제를 막기 어려우며, 코드가 flexible하지도 않다. 

 

2) argument가 있는 함수 : function(a,b)

const giveAccessTo = (name) => 'Access Granted to ' + name;

function letUserLogin(user) {
  // 이제 함수가 어떤 데이터를 사용해야 할지를 알려줄 수 있다.
  let array = [];
  for (let i = 0; i < 1000000; i++) {
    array.push(i);
  }
  return giveAccessTo(user);
}
letUserLogin('Adam');
letUserLogin('Eva');

 

함수에 인자를 전달함으로써, 전달 받은 매개변수는 함수가 활용할 수 있는 데이터가 된다. DRY의 문제를 해결할 수 있다.

즉 함수에 인자를 전달하는 것은, 그 함수가 '어떤 데이터를 활용해야 하는지'를 알려주는 길잡이가 된다.

 

3) 고차함수 : Higher Order Function

const giveAccessTo = (name) => 'Access Granted to ' + name;

function authenticate(verify) {
  let array = [];
  for (let i = 0; i < verify; i++) {
    array.push(i);
  }
  return true;
}

function letPerson(person, fn) {
  // 무슨 데이터를 사용할지 알려줄 뿐 아니라,
  // 무엇을 해야할지도 알려줄 수 있다.
  if (person.level === 'admin') {
    fn(500000);
  } else if (person.level === 'user') {
    fn(10000);
  }
  return giveAccessTo(person.name);
}

letPerson({level: 'user', name: 'Tim'}, authenticate)

 

고차함수를 활용하면, 함수에게 단순히 '어떤 데이터를 활용할 수 있는지'를 알려줄 뿐 아니라, 그 데이터를 기반으로 '무엇을 해야할지'도 더욱 generic한(일반적인) 방식으로, 즉 코드의 재사용성이 높아지는 방식으로 사용할 수 있다.

위 함수는 authenticate라는 함수를 지정해놓고, 함수가 활용할 인자로 person이라는 객체와 함수를 받게 해 놓았다. 그래서 만약 person이 admin, 즉 관리자라면(무슨 데이터를 사용할지) 로그인 절차를 50만번 돌아서 더 복잡하게 수행하도록(무엇을 해야할지) 지정해주고 있다. 

댓글