[JavaScript] 배열, 객체

2023-09-18

배열


배열(array)은 순서가 있는 데이터 리스트입니다. 자바스크립트에서 배열을 만드는 방법은 대괄호 [] 안에 원하는 요소를 쉼표로 구분하여 나열하는 것입니다.

let arr = [item1, item2...];

배열의 요소에는 모든 자료형이 허용됩니다. 배열에는 숫자 뿐 아니라 문자열, 객체, 다른 배열 등을 요소로 담을 수 있습니다.

요소에 접근하기

배열 요소에 접근하려면 대괄호 안에 요소의 인덱스를 넣어주면 됩니다. 배열의 인덱스는 0부터 시작합니다.

let fruits = ["사과", "배", "오렌지"];
 
console.log(fruits[0]); // "사과"
console.log(fruits[1]); // "배"
console.log(fruits[2]); // "오렌지"

배열 길이

배열의 길이는 length 프로퍼티를 이용해 알아낼 수 있습니다.

let fruits = ["사과", "배", "오렌지"];
 
console.log(fruits.length); // 3

배열을 순회하기

배열을 순회하려면 다양한 방법을 사용할 수 있습니다. 가장 간단한 방법은 for 반복문을 이용하는 것입니다.

let fruits = ["사과", "배", "오렌지"];
 
for (let i = 0; i < fruits.length; i++) {
  console.log(fruits[i]);
}

그리고 배열 내장 메서드 forEach를 이용하는 방법도 있습니다.

let fruits = ["사과", "배", "오렌지"];
 
fruits.forEach(function(item, index, array) {
  console.log(item, index);
});

배열 끝에 요소 추가하기

배열의 끝에 요소를 추가하려면 push 메서드를 이용하면 됩니다.

let fruits = ["사과", "배"];
 
fruits.push("오렌지");
 
console.log(fruits); // ["사과", "배", "오렌지"]

배열 앞에 요소 추가하기

배열의 앞에 요소를 추가하려면 unshift 메서드를 이용하면 됩니다.

let fruits = ["사과", "배"];
 
fruits.unshift("오렌지");
 
console.log(fruits); // ["오렌지", "사과", "배"]

배열 끝 요소 제거하기

배열의 끝 요소를 제거하려면 pop 메서드를 이용하면 됩니다.

let fruits = ["사과", "배", "오렌지"];
 
fruits.pop();
 
console.log(fruits); // ["사과", "배"]

배열 앞 요소 제거하기

배열의 앞 요소를 제거하려면 shift 메서드를 이용하면 됩니다.

let fruits = ["사과", "배", "오렌지"];
 
fruits.shift();
 
console.log(fruits); // ["배", "오렌지"]

배열 내 요소 찾기

배열 내 특정 요소의 인덱스를 찾으려면 indexOf 메서드를 이용하면 됩니다.

let fruits = ["사과", "배", "오렌지"];
 
console.log(fruits.indexOf("배")); // 1

배열 내 요소를 문자열로 변환하기

배열 내 요소를 문자열로 변환하려면 join 메서드를 이용하면 됩니다.

let fruits = ["사과", "배", "오렌지"];
 
console.log(fruits.join("-")); // "사과-배-오렌지"

배열 복사하기

배열을 복사할 때는 slice 메서드를 이용하면 됩니다.

let fruits = ["사과", "배", "오렌지"];
 
let fruitsCopy = fruits.slice();

배열 정렬하기

배열을 정렬할 때는 sort 메서드를 이용하면 됩니다. 이 때, 배열 내 요소가 문자열인 경우, 기본적으로 유니코드 코드 포인트 순서로 정렬됩니다.

let fruits = ["사과", "배", "오렌지"];
 
fruits.sort();
 
console.log(fruits); // ["배", "사과", "오렌지"]

배열 역순으로 뒤집기

배열 내 요소의 순서를 역순으로 뒤집으려면 reverse 메서드를 이용하면 됩니다.

let fruits = ["사과", "배", "오렌지"];
 
fruits.reverse();
 
console.log(fruits); // ["오렌지", "배", "사과"]

배열 내 숫자 요소 합계 구하기

배열 내 숫자 요소의 합계를 구하려면 reduce 메서드를 이용하면 됩니다.

let arr = [1, 2, 3, 4, 5];
 
let result = arr.reduce(function(sum, current) {
  return sum + current;
}, 0);
 
console.log(result); // 15

객체


자바스크립트엔 여덟 가지 자료형이 있습니다. 이 중 일곱 개는 오직 하나의 데이터(문자열, 숫자 등)만 담을 수 있어 '원시형(primitive type)'이라 부릅니다.

그런데 객체형은 원시형과 달리 다양한 데이터를 담을 수 있습니다. 키로 구분된 데이터 집합이나 복잡한 개체(entity)를 저장할 수 있습니다.

객체는 중괄호 {…}를 이용해 만들 수 있습니다. 중괄호 안에는 키(key): 값(value) 쌍으로 구성된 *프로퍼티(property)*를 여러 개 넣을 수 있는데, key엔 문자형, value엔 모든 자료형이 허용됩니다. 프로퍼티 키는 ‘프로퍼티 이름’이라고도 부릅니다.

서랍장을 상상하면 객체를 이해하기 쉽습니다. 서랍장 안 파일은 프로퍼티, 파일 각각에 붙어있는 이름표는 객체의 키라고 생각하시면 됩니다. 복잡한 서랍장 안에서 이름표를 보고 원하는 파일을 쉽게 찾을 수 있듯이, 객체에선 키를 이용해 프로퍼티를 쉽게 찾을 수 있습니다. 추가나 삭제도 마찬가지입니다.

객체 생성 방법

let user = new Object(); // '객체 생성자' 문법
let user = {}; // '객체 리터럴' 문법

리터럴과 프로퍼티

자바스크립트에서 객체를 만드는 방법에는 객체 생성자와 객체 리터럴 두 가지가 있습니다.

객체 생성자는 new Object()와 같이 사용하며, 객체 리터럴은 중괄호 {} 안에 프로퍼티를 정의하여 사용합니다. 이 두 가지 방법 모두 객체를 만들어낼 수 있지만, 객체 리터럴 방식이 더 직관적이고 간결하므로 일반적으로 더 많이 사용됩니다.

중괄호 {...} 안에는 '키: 값' 쌍으로 구성된 프로퍼티가 들어갑니다.

let user = {  // 중괄호를 이용해 객체를 만듦
  name: "John",  // 프로퍼티 한 쌍
  age: 30  // 프로퍼티 한 쌍
};
 
// 점 표기법(dot notation)을 이용하면 프로퍼티 값을 읽는 것도 가능합니다.
console.log(user.name); // John
console.log(user.age); // 30

프로퍼티 값엔 모든 자료형이 올 수 있습니다. 불린형 프로퍼티를 추가해봅시다.

user.isAdmin = true; // {name = "John", age: 30, isAdimin: true

delete 연산자를 사용하면 프로퍼티를 삭제할 수 있습니다.

delete user.age; // {name = "John", isAdimin: true}

여러 단어를 조합해 프로퍼티 이름을 만든 경우엔 프로퍼티 이름을 따옴표로 묶어줘야 합니다.

let user = {
  name: "John",
  age: 30,
  "likes birds": true  // 복수의 단어는 따옴표로 묶어야 합니다.
};

대괄호 표기법

여러 단어를 조합해 프로퍼티 키를 만든 경우엔, 점 표기법을 사용해 프로퍼티 값을 읽을 수 없습니다. 그래서 대괄호 표기법을 사용합니다.

let user = {};
 
// set
user["likes birds"] = true;
 
// get
console.log(user["likes birds"]); // true
 
// delete
delete user["likes birds"];

계산된 프로퍼티

객체를 만들 때 객체 리터럴 안의 프로퍼티 키가 대괄호로 둘러싸여 있는 경우, 이를 *계산된 프로퍼티(computed property)*라고 부릅니다.

let fruit = prompt("어떤 과일을 구매하시겠습니까?", "apple");
 
let bag = {
  [fruit]: 5, // 변수 fruit에서 프로퍼티 이름을 동적으로 받아 옵니다.
};
 
console.log( bag.apple ); // fruit에 "apple"이 할당되었다면, 5가 출력됩니다.

대괄호 표기법은 프로퍼티 이름과 값의 제약을 없애주기 때문에 점 표기법보다 훨씬 강력합니다. 그런데 작성하기 번거롭다는 단점이 있습니다.

'in' 연산자로 프로퍼티 존재 여부 확인하기

자바스크립트 객체의 중요한 특징 중 하나는 다른 언어와는 달리, 존재하지 않는 프로퍼티에 접근하려 해도 에러가 발생하지 않고 undefined를 반환한다는 것입니다.

let user = {};
alert(user.noSuchProperty === undefined); // true는 '프로퍼티가 존재하지 않음'을 의미합니다.

이렇게 undefined와 비교하는 것 이외에도 연산자 in을 사용하면 프로퍼티 존재 여부를 확인할 수 있습니다.

문법은 다음과 같습니다.

 "key" in object
let user = {name: "John", age: 30};
alert("age" in user); // user.age가 존재하므로 true가 출력됩니다.
alert("blabla" in user); // user.blabla는 존재하지 않기 때문에 false가 출력됩니다.

객체 정렬 방식

객체는 '특별한 방식으로 정렬’됩니다. 정수 프로퍼티(integer property)는 자동으로 정렬되고, 그 외의 프로퍼티는 객체에 추가한 순서 그대로 정렬됩니다. 자세한 내용은 예제를 통해 살펴봅시다.

아래 객체엔 국제전화 나라 번호가 담겨있습니다.

let codes = {
  "49": "독일",
  "41": "스위스",
  "44": "영국",
  // ..,
  "1": "미국"
};
 
for (let code in codes) {
  alert(code); // 1, 41, 44, 49
}

정수 프로퍼티(integer property)란 변형 없이 정수에서 왔다 갔다 할 수 있는 문자열을 의미합니다.

정수 프로퍼티로 설정하지 않기 위해서는 숫자 앞에 ‘+'를 붙이고 출력할 때 ‘+’를 붙여줍니다.

아래 코드는 이 예시를 보여줍니다.

let codes = {
  "+49": "독일",
  "+41": "스위스",
  "+44": "영국",
  // ..,
  "+1": "미국"
};
 
for (let code in codes) {
  alert( +code ); // 49, 41, 44, 1
}

참조에 의한 객체 복사

자바스크립트에서 객체는 참조에 의해 할당되고 복사됩니다. 객체가 할당된 변수를 복사하면 객체가 아닌 '참조'(객체가 저장된 메모리 주소)가 복사됩니다.

따라서, 두 변수가 같은 객체를 참조하고 있으면, 하나의 변수를 통해 객체를 수정하면 나머지 변수에서도 변경사항이 반영됩니다.

객체를 복사하려면, 참조 대신 객체의 복사본을 만들어야 합니다. 이를 '얕은 복사(shallow copy)'와 '깊은 복사(deep copy)'라고 합니다.

'얕은 복사'는 객체의 프로퍼티 값을 복사하지만, 객체 내부의 객체(중첩 객체)는 참조로 복사됩니다. 이에 비해 '깊은 복사'는 객체를 완전히 새로운 객체로 복사합니다.

얕은 복사를 하는 가장 간단한 방법은 {...obj}Object.assign({}, obj)를 사용하는 것입니다. 깊은 복사는 객체를 순회하며 프로퍼티 값을 복사하는 방식으로 구현할 수 있습니다.

// 얕은 복사
let obj = {a: 1, b: {c: 2}};
let copy = {...obj}; // 또는 Object.assign({}, obj);
 
// 깊은 복사
function deepCopy(obj) {
  let copy = {};
 
  for (let key in obj) {
    if (typeof obj[key] == "object") {
      copy[key] = deepCopy(obj[key]);
    } else {
      copy[key] = obj[key];
    }
  }
 
  return copy;
}
 
let obj = {a: 1, b: {c: 2}};
let copy = deepCopy(obj);
 

메서드와 this


객체 내부엔 변수 뿐만 아니라 함수도 존재할 수 있습니다. 객체 프로퍼티에 할당된 함수를 *메서드(method)*라고 부릅니다.

메서드는 객체 데이터에 접근할 수 있습니다. 메서드는 객체가 어떻게 보이는지, 동작하는지, 객체 데이터로 무언가를 할 수 있는지를 나타내는 객체의 기능을 구현할 때 사용합니다.

메서드는 다른 함수와 동일한 방식으로 정의할 수 있습니다. 하지만 메서드에는 특별한 문법적 제약이 없습니다.

let user = {
  name: "John",
  age: 30
};
 
user.sayHi = function() {
  alert("안녕하세요!");
};
 
user.sayHi(); // 안녕하세요!

위 예시에선 함수를 user 객체에 할당하여 메서드를 정의했습니다.

메서드는 객체 데이터에 접근할 권한을 가지고 있기 때문에, this를 사용해 객체의 프로퍼티에 접근할 수 있습니다. this는 자동으로 현재 객체를 참조합니다.

let user = {
  name: "John",
  age: 30,
 
  sayHi() {
    alert(this.name);
  }
 
};
 
user.sayHi(); // John

this를 사용해 객체 내부의 프로퍼티에 접근할 수도 있습니다.

let user = {
  name: "John",
  age: 30,
 
  sayHi() {
    alert(user.name); // 'this' 대신 'user'를 이용해 프로퍼티에 접근합니다.
  }
 
};
 
user.sayHi(); // John
 

하지만 this를 이용하면 객체에 할당된 변수나 함수를 재사용할 수 있습니다.

let user = {
  name: "John",
  age: 30,
 
  sayHi() {
    alert(this.name);
  }
 
};
 
let admin = user;
user = null;
 
admin.sayHi(); // "John"이 출력됩니다. user가 null이 되었지만, admin에는 여전히 user 객체의 참조 값이 저장되어 있습니다.
 

'메서드 단축 구문'

메서드를 추가할 때 함수를 사용하는 대신, 다음과 같이 메서드 단축 구문을 사용할 수 있습니다.

// 키와 값이 동일한 이름을 가질 때만 사용할 수 있습니다.
let user = {
  name: "John",
  age: 30,
 
  sayHi() {
    // 'sayHi: function()'과 동일합니다.
    alert(this.name);
  }
 
};

'getter'와 'setter'

객체 프로퍼티에는 값뿐만 아니라 gettersetter함수를 지정할 수 있습니다.

getter와 setter는 사용자 입장에서 프로퍼티 값을 읽거나 쓸 때, 마치 객체 내부의 변수에 접근하는 것처럼 보입니다.

getter와 setter는 함수이며, 함수 이름 앞에 get과 set을 붙여서 정의합니다.

let user = {
  name: "John",
  surname: "Smith",
 
  get fullName() {
    return `${this.name} ${this.surname}`;
  },
 
  set fullName(value) {  // fullName이라는 프로퍼티에 값을 할당하려 하면 이 세터 함수가 호출됩니다.
    [this.name, this.surname] = value.split(" ");
  }
};
 
alert(user.fullName); // John Smith
 
user.fullName = "Alice Cooper";
 
alert(user.name); // Alice
alert(user.surname); // Cooper

getter와 setter는 obj.__proto__안에 정의된 특수한 프로퍼티인 get과 set을 이용해 구현됩니다.

객체 생성자와 'new'

객체 생성자(constructor)를 사용하면 동일한 구조의 객체를 여러 개 만들 수 있습니다.

객체 생성자는 함수 이름의 첫 글자를 대문자로 쓰고, 반드시 new 연산자와 함께 호출해야 합니다.

function User(name) {
  this.name = name;
  this.isAdmin = false;
}
 
let user = new User("Jack");
 
alert(user.name); // Jack
alert(user.isAdmin); // false
 

객체 생성자를 사용하면, 동일한 프로퍼티를 가진 객체를 여러 개 만들 수 있습니다. 또한, 객체 생성자 안에 메서드를 추가하여 해당 객체에만 적용될 수 있도록 할 수 있습니다.

제목 없는 데이터베이스

javascriptarrayobject

프로필 사진
TaeWoo Kim
Junior Frontend Engineer