Week 3 - JavaScript 08. 배열과 함수가 객체인 이유

김민재·2021년 8월 11일
5

TIL, WeCode, Course 

목록 보기
8/48
post-thumbnail

*🔐Study Keyword :

🔑배열과 함수 모두 ✅객체로 왜 그러한지, 어떻게 쓸 수 있는지까지 알아보장!

- 배열과 함수는 객체?!

  • WHAT IS❓

  • 우리가 배운 데이터 타입에 따르면 자바스크립트는 크게 기본형 타입(primitive type)과 참조형 타입(Reference Type) 으로 나눠지고
    이 참조형 데이터 타입에는🗝 오늘의 키워드 🔐객체가 있고 이 객체의 하위 부류로 🔑배열과 🗝️함수가 포함되어 있다

  • 이제 우리가 알아야할건 🔑배열과 🗝️함수를 나눠서
    1> 왜 배열과 함수가 객체인지?
    2> 어떻게 하면 객체인 배열과 함수를 더 잘 다룰 수 있는지!
    두 가지를 중점으로 살펴보자~ 레고!

  • WHY❔❕

- 왜 배열과 함수가 객체냐고요😓!

  • 배열은 자바스크립트의 일곱 가지 원시 자료형에 해당하지 않고, 원시 자료형이 아닌 객체형에 속하기 때문에 객체처럼 동작한다.

🔐객체란?

  • 우선 🔐객체에 대해서 짚고 넘어가자!

    🔐객체라는 자료구조는 를 사용해 식별할 수 있는 값(키의 값)을 담은 컬렉션으로 이를 이용해 데이터를 저장할 수 있고 객체만으로도 다양한 작업들이 충분히 가능하다.

  • Q. 그렇다면 🔑배열은 왜 만든걸까 🤷‍♂️?!
  • A. 개발을 하다 보면 첫 번째 요소, 두 번째 요소, 세 번째 요소 등과 같이 순서가 있는 컬렉션이 필요할 때가 있다.
    (EX> 사용자나 물건, HTML 요소 목록같이 일목요연하게 순서를 만들어 정렬하는 작업 등)

<문제점>

  • 이렇게 순서가 있는 컬렉션을 다뤄야 할 땐 🔐객체를 사용하면 순서와 관련된 메서드가 없어 불편하다.
  • 객체는 태생이 순서를 고려하지 않고 만들어진 자료구조이기 때문에 객체를 이용하면 새로운 프로퍼티를 기존 프로퍼티 사이에 끼워 넣는 것도 불가능하다.

<해결책>

  • 이처럼 순서가 있는 컬렉션을 저장해야하는 상황이 생길 때 쓰는 자료구조가 바로 🔑배열이다.

1> 왜 배열이 객체일까?

<배열의 내부 동작원리>

  • 1> 🔑배열특별한 종류의 객체입니다.
    • 1.1>배열 arr의 요소를 접근할때 arr[0]처럼 대괄호를 사용하는 방식도 사실은 객체 문법에서 왔다.(대박이죠..!)
    • 1.2> 다만 🔑배열키가 숫자라는 점이 특징이다.
  • 2> 숫자형 키(배열에선 인덱스)를 사용함으로써 배열은 객체 기본 기능 이외에도 순서가 있는 컬렉션을 제어할 수 있는 특별한 메서드를 제공를 가진다.
    (EX> 메서드 뿐만 아니라 length 프로퍼티(배열의 길이를 알려주는) 역시 제공)

2> 어떻게 객체인 배열을 더 잘 다룰까!

<배열이 객체처럼 동작하는 과정들>

  • 1> 배열은 객체와 마찬가지로 참조를 통해 복사!
<script>
let fruits = ["사과", "오렌지", "배"]
// 1. 배열을 값으로 가진 변수 fruits를 새로운 변수에 재할당하여 복사
let arr = fruits; // 이때 값이 아닌 참조를 복사(따라서 현재 두 변수가 같은 객체를 참조한다)
console.log( arr === fruits ); // true
// 1. 배열을 값으로 가진 변수 fruits를 수정 
arr.push("딸기"); // 이때 역시 참조를 이용해 배열을 수정
console.log(fruits); // ["사과", "오렌지", "배", "딸기"] - 요소가 네 개로 됨
</script>
  • 2.> 배열은 객체처럼 원하는 프로퍼티를 추가해도 문제가 발생하진 X!
<script>
let fruits = []; // 빈 배열을 하나 생성
fruits[10] = 5; // 배열의 길이보다 훨씬 큰 숫자를 사용해 프로퍼티를 할당  
fruits.age = 25; // 임의의 이름으로 프로퍼티를 만들어도 문제 X
console.log(fruits) // [empty * 9, 5]
</script>

🔅주의🔅)

다만 이렇게 코드를 작성하면 자바스크립트 엔진이 배열을 일반 객체처럼 다루게 되어 배열 특유의 이점이 사라지니 배열은 배열답게 사용하자.

    1. 배열은 객체형이므 for..in을 사용하는 것도 가능!
<script>
let arr = ["사과", "오렌지", "배"];
for (let key in arr) {
  console.log( key ); // 0, 1, 2 => 키를 조회, 즉 인덱스 값이 나온다 
  console.log( arr[key] ); // 사과, 오렌지, 배 => 배열[키], 배열의 요소가 나온다.
}
</script>
  • BUT> for..in 반복문은 배열이 아닌 객체와 함께 사용할 때 최적화되어 있어서 배열에 사용하면 객체에 사용하는 것 대비 10~100배 정도 느리다는 것!
  • 따라서 배열엔 되도록 for..in 반복문을 쓰지말고 배열의 다른 순회 문법인 for..of 반복문을 사용하자.
<script>
let arr = ["사과", "오렌지", "배"];
// 배열 요소를 대상으로 반복 작업을 수행합니다.
for (let key of arr) {
  console.log( key ); // "사과", "오렌지", "배"
}
</script>
  • 요약

  • 이러한 이유들로 인해 🔑배열의 본질은 바로 객체(특수한 형태의)순서가 있는 자료를 저장하고 관리하는 용도에 최적화된 자료구조입니다.
  • 배열 내장 메서드(push, pop, slice 등등)들 역시 이러한 용도에 맞게 만들어진 것으로 배열을 사용할 땐 목적에 맞게 사용하는 것을 권장합니다.
  • 임의의 키(숫자형이 아닌)를 사용해야 한다면 배열보단 일반 객체 {}가 적합한 자료구조일 것이다.

3> 왜 함수는 객체일까?

  • Q. 그렇다면 🔑배열은 왜 만든걸까 🤷‍♂️?!
  • A. 개발을 하다 보면 첫 번째 요소, 두 번째 요소, 세 번째 요소 등과 같이 순서가 있는 컬렉션이 필요할 때가 있다.
    (EX> 사용자나 물건, HTML 요소 목록같이 일목요연하게 순서를 만들어 정렬하는 작업 등)

<문제점>

  • 이렇게 순서가 있는 컬렉션을 다뤄야 할 땐 🔐객체를 사용하면 순서와 관련된 메서드가 없어 불편하다.
  • 객체는 태생이 순서를 고려하지 않고 만들어진 자료구조이기 때문에 객체를 이용하면 새로운 프로퍼티를 기존 프로퍼티 사이에 끼워 넣는 것도 불가능하다.

<해결책>

  • 이처럼 순서가 있는 컬렉션을 저장해야하는 상황이 생길 때 쓰는 자료구조가 바로 🔑배열이다.

3> 왜 🗝️함수는 객체일까?

  • Q. 자바스크립트에서 함수는 객체 타입의 값으로 취급됩니다. 왜 그럴까요 🤷‍♂️?!
  • A. 그 이유는 바로 객체가 값이기 때문에 함수를 일급 객체로 여깁니다🙆‍♂️!

일급객체란?

  • 자바스크립트에서 🗝️함수는 일급 객체인데 *다음의 조건을 만족하면 일급 객체입니다
1. 변수(variable)나 자료구조(객체, 배열)에 저장할 수 있다.
2. 함수의 인자(parameter)로 전달할 수 있다.
3. 함수의 반환값(return value)으로 전달할 수 있다. 
  • 이처럼 함수가 일급 객체라는 건 함수를 객체와 동일하게 사용할 수 있다는 것을 의미합니다. 객체는 값이므로 함수 역시 값과 동일하게 취급하는 거죠.
  • 자바스크립트의 함수는 값처럼 변수에 할당할 수 도 있고 프로퍼티 값이 될 수도, 배열의 요소가 될 수 도 있습니다. 이렇게 값의 성질을 갖는 객체를 일급객체라고 합니다.

<함수가 객체처럼 동작>

    1. 리터럴에 의해 생성
<script>
//변수 variable에 함수 리터럴을 할당한 식
const cal = function add(x, y){
	return x + y;
}
</script>

위 코드처럼 함수 리터럴을 변수에 할당하고 있는데요. 여기서 리터럴이란 값을 생성하기 위한 표기법(사람이 이해할 수 있는 문자 또는 약속된 기호를 사용)입니다. 따라서 함수 리터럴도 평가되어 값을 생성하고 있습니다.

    1. 변수나 프로퍼티의 값으로 할당이 가능
<script>
// 변수에 함수 할당
const name = function() { return 'minjae'; };
console.log(name()); // minjae
// 프로퍼티에 함수 할당
const obj = {};
obj.langauge = function() { return 'javaScript'; };
console.log(obj.langauge()); // javaScript
</script>
  • 위 코드의 langauge처럼 객체의 프로퍼티에도 함수를 할당할 수 있고 배열의 원소로도 할당이 가능하다.
    1. 함수의 인자로 전달 가능
<script>
// 함수 표현식으로 passer() 함수를 생성
const passer = function(func) {
  func(); // 인자로 함수를 넘겨받고 넘겨받은 func() 함수를 호출한다.
}
//passer() 함수 호출 시
passer(function(){ // passer 함수의 인수로 함수 자체를 전달한다.
  console.log('나는 함수의 인자로 전달되었습니당!');
});// '나는 함수의 인자로 전달되었습니당!'
</script>
  • passer() 함수를 호출 시 함수 자체를 func 인자로 넘겨서 passer() 함수 내부에서 func 매개변수로 인자에 넘겨진 함수를 호출합니다.
    1. 함수의 리턴값으로 리턴 가능
<script>
// 함수를 다른 함수의 리턴값으로 활용한 코드
// 함수를 리턴하는 foo() 함수 정의
const foo = function() {
    return function() {     // 함수를 리턴
        console.log('이 함수는 함수를 반환한다.');
    };
};
// foo() 함수가 호출되면, 리턴값으로 전달되는 익명함수가 bar 변수에 저장된다.
const bar = foo();
// 익명함수를 호출하기 위해서 ()인 함수호출 연산자를 이용해 bar()로 익명함수를 호출, 실행한다.
bar(); // ('이 함수는 함수를 반환한다.')
</script>
    1. 동적으로 프로퍼티를 생성 및 할당 가능
<script>
function minus(x,y) {
    return x - y;
}
// 함수 역시 객체처럼 프로퍼티를 가질 수 있다.
// 함수 객체에 anwser 프로퍼티를 추가하고 값으로 함수를 호출하여 넘겨준다.
minus.result = minus(4,1);
console.log(minus.result); // 1
</script>
  • 함수 자체가 일반 객체처럼 프로퍼티를 생성하고 할당이 가능합니다.
  • minus()함수는 result 프로퍼티를 생성하고 minus()함수 호출 결과 값을 생성한 함수의 result 프로퍼티에 저장할 수 있습니다.
  • 일반 객체의 접근방식처럼 minus.result를 이용해 접근도 가능하죠.
  • 요약

  • 자바스크립트에서 함수는 특정기능의 코드를 수행할 뿐만 아니라, 일반 객체처럼 자신의 프로퍼티를 가질 수 있는 특별한 객체(일급)입니다.
  • 일급 객체로서 함수가 가지는 가장 큰 특징은 일반 객체와 같이 함수의 매개변수에 전달할 수 있으며 함수의 반환값으로도 사용할 수 있다는 점 입니다.
  • 일반 객체와의 차이점은 일반 객체는 호출할 수 없지만 함수 객체는 호출할 수 있고 일반 객체엔 없는 함수 고유의 프로퍼티를 소유합니다

*💡conclusion

  • 함수와 배열 모두 객체입니다! 객체에 대해서 공부하시다보면 더 이해가 잘 갈거같아요! 배열이 가진 특수한 메서드 함수 고유의 프로퍼티와 같이 객체와 다른 배열과 함수만의 특징 역시 공부하시면 더 좋습니당..!

#📑Study Source

  1. 책 - 딥다이브
  2. 자바스크립트 튜토리얼 배열 편 - https://ko.javascript.info/array
profile
자기 신뢰의 힘을 믿고 실천하는 개발자가 되고자합니다.

0개의 댓글