songin.dev님의 블로그

[Let's Get IT 자바스크립트 프로그래밍] 2장 기본 문법 배우기 - 객체 본문

Developer/Langauge

[Let's Get IT 자바스크립트 프로그래밍] 2장 기본 문법 배우기 - 객체

songin.dev 2022. 6. 23. 18:05
728x90
객체

객체

객체(object)는 자료형의 일종으로 다양한 값을 모아 둔 또 다른 값입니다. 객체의 종류는 크게 배열(array), 함수(function), 배열이나 함수가 아닌 객체로 나눌 수 있다.

배열

const fruits = ['사과', '오렌지', '배', '딸기'];

배열을 만들려면 대괄호 [ ]로 값들을 감싸면 됩니다. 각각의 값은 쉼표로 구분합니다.

배열 이름 뒤에 불러오고 싶은 값의 자릿수를 적어주면 배열 내부의 값을 개별적으로 불러올 수도 있습니다.

프로그래밍에서는 이런 자릿수를 인덱스(index)라고 합니다.

const fruits = ['사과', '오렌지', '배', '딸기'];

console.log(fruits[0]); // 사과
console.log(fruits[1]); // 오렌지
console.log(fruits[2]); // 배
console.log(fruits[3]); // 딸기

배열 안에 있는 값의 자료형은 모두 같지 않아도 됩니다. 배열 안에 다른 배열이나 변수를 넣을 수 있습니다.

const arrayOfArray = [[1, 2, 3],[4, 5]];
arrayOfArray[0]; // [1, 2, 3]
const a = 10;
const b = 20;
const variableArray = [a, b, 30];
variableArray[1]; // 20 (b의 값)

arrayOfArray 배열을 보면 배열 내부에 배열이 들어 있습니다. arrayOfArray [0]을 하면 [1, 2, 3] 이 나오는데 이 또한 배열입니다.

이러한 배열을 이차원 배열이라고 합니다.

const everything = ['사과', 1, underfined, true, '배열', null];
const buplicated = ['가', '가', '가', '가', '가'];
const empty = [];

배열 내부의 값을 요소(element) 라고 합니다. everything 배열에는 요소가 6개가 들어 있고, empty 배열에는 요소가 0개 있습니다.

프로그래밍으로 요소의 개수를 구할 수 있습니다.

 

배열의 요소 개수 구하기

배열 이름 뒤에 .length를 붙이면 배열의 요소 개수를 구할 수 있습니다.

const everything = ['사과', 1, underfined, true, '배열', null];
console.log(everythig.length); // 6

빈 값도 유효한 값이기 때문에  요소 개수를 셀 때 포함됩니다.

const emptyValue = [null, undefined, false, '', NaN];
console.log(emptyValue.length); // 5

배열의 요소 개수를 활용해 원하는 인덱스의 요소를 찾을 수 있습니다.

배열의 요소 개수가 항상 마지막 인덱스보다 1 크기 때문에 배열의 요소 개수에서 1을 빼면 마지막 요소의 인덱스가 됩니다.

이를 이용해 마지막 요소의 값을 찾을 수 있습니다.

const findLastElement = ['a', 'b', 'c', 'd', 'e'];
console.log(findLastElement[findLastElement.length-1]); // e
1분 퀴즈
arr이라는 배열이 있을 때, 배열의 마지막에서 세 번째 요소를 찾아보세요.

정답 및 해설

console.log(arr[arr.length-3]);

// 배열의 마지막 요소의 인덱스가 length-1 이기 때문에 마지막 3번째 요소는 .length-3을 통해 찾을 수 있다.

배열의 요소 추가하기

배열을 만들고 나면 중간에 배열을 수정할 수 있습니다.

배열에 요소를 추가할 수도 있고, 특정 인덱스의 요소를 수정하거나 제거할 수도 있습니다.

const target = ['a', 'b', 'c', 'd', 'e'];
target[target.length] = 'f';
console.log(target);

// ['a', 'b', 'c', 'd', 'e', 'f'];

배열의 마지막 요소의 인덱스가 배열. length-1이기 때문에 변수에 배열. length를 통해 마지막 인덱스에 요소를 추가할 수 있습니다.

const target = ['나', '다', '라', '마', '바'];
target.unshift('가');
console.log(target);

// ['가', '나', '다', '라', '마', '바'];

배열. unshift라는 기능을 실행하면 맨 앞에 요소를 추가할 수 있습니다.

const target = ['가', '나', '다', '라', '마'];
target.push('바');
console.log(target);

// ['가', '나', '다', '라', '마', '바']

배열. length를 통해 맨 뒤에 요소를 추가하는 방법도 있습니다만,. push를 이용해서도 가능합니다.

 

const(상수)인데 수정 가능한 이유

const에는 새로운 값을 대입(=)하지 못한다고 기억하면 됩니다.

const에 객체(배열, 함수, 객체 리터럴)가 대입되면 객체 내부의 속성이나 배열의 요소는 수정할 수 있습니다.

 

const target2 = ['a', 'b', 'c', 'd', 'e'];
target2 = ['f', 'g']; // 불가능
target2[0] = 'h'; // 가능

배열의 요소 수정하기

앞서 확인한 것과 같이 원하는 인덱스에 바꿀 값을 넣으면 됩니다.

 

배열의 요소 제거하기

배열.pop()를 이용하면 맨 마지막 요소가 제거됩니다.

const target = ['가', '나', '다', '라', '마'];
target.pop();
console.log(target);

// ['가', '나', '다', '라']

반대로 첫 번째 요소를 제거하기 위해서는 배열. shift()를 사용합니다.

const target = ['가', '나', '다', '라', '마'];
target.shift();
console.log(target);

// ['나', '다', '라', '마']

중간 요소를 제거하는 위해서는 배열.splice()를 사용합니다.

const target = ['가', '나', '다', '라', '마'];
target.splice(1, 1);
console.log(target);

// ['가', '다', '라', '마']

splice 기능에서는 두 개의 값을 사용합니다. 첫 번째는 시작 인덱스이고, 두 번째는 제거할 요소의 개수입니다.

const target = ['가', '나', '다', '라', '마'];
target.splice(1);
console.log(target);

// ['가']

splice()에 하나의 숫자값을 넣게 되면 해당 인덱스부터 끝까지 모든 요소가 제거됩니다.

splice로 값만 제거하는 것이 아니라 제거한 자리에 다른 값을 넣을 수 있습니다. 

const target = ['가', '나', '다', '라', '마'];
target.splice(1, 3, '타', '파');
console.log(target);

// ['가', '타', '파', '마']

splice(1, 3, '타', '파')는 인덱스 1부터 3개 요소를 먼저 제거하고 요소를 제거한 자리에 '타'와 '파'를 채워 넣습니다.

 

배열에서 요소 찾기

includes 기능을 사용하여 배열에 특정 요소가 있는지 찾아볼 수 있습니다.

const target = ['가', '나', '다', '라', '마'];
const result = target.includes('다');
const result2 = target.includes('카');
console.log(result);
console.log(result2);

// true
// false

includes에 주어진 값이 배열에 존재하면 true가 되고, 존재하지 않으면 false가 됩니다.

indexOf와 lastIndexOf를 사용하여 찾고자 하는 값이 몇 번째 인덱스에 위치하고 있는지 알 수 있습니다.

const target = ['라', '나', '다', '라', '다'];

const result = target.indexOf('다');
const result2 = target.lastIndexOf('라');
const result3 = target.indexOf('가');

console.log(result); // 2
console.log(result2); // 3
console.log(result3); // -1

indexOf는 앞에서부터 주어진 값이 있는지 찾고, lastIndexOf는 뒤에서부터 찾습니다. 따라서 '다'가 인덱스 2, 4에 위치하지만 IndexOf는 앞에서부터 찾으므로 결괏값이 2가 됩니다. '라'는 인덱스 0, 3에 위치하지만, lastIndexOf는 뒤에서부터 찾으므로 결괏값이 3이 됩니다.

배열 안에 존재하지 않는 값의 인덱스를 찾으면 결괏값은 -1이 됩니다.

 

배열 반복하기

배열은 값들을 나열한 것이기 때문에 반복문과 같이 사용하는 경우가 많습니다.

while 문이나 for 문 모두 사용할 수 있습니다.

const target = ['가', '나', '다', '라', '마'];
let i = 0;
while (i < target.length) {
  console.log(target[i]);
  i++;
}

/*
가
나
다
라
마
*/
const target = ['가', '나', '다', '라', '마'];
for(let i = 0; < target.length; i++) {
  console.log(target[i]);
}

/*
가
나
다
라
마
*/
1분 퀴즈
다음 배열에서 '라'를 모두 제거하세요. indexOf와 splice를 사용하세요.
const arr = ['가', '라', '다', '라', '마', '라'];
힌트 : 반복문을 사용하면 모두 제거할 수 있습니다.
const arr = ['가', '라', '다', '라', '마', '라'];
let index = arr.indexOf('라');
while(index > -1) {
  arr.splice(index, 1);
  index = arr.indexOf('라');
}
console.log(arr);

/* 
index라는 변수에 arr.indexOf('라')를 초기값으로 설정한다.
while 문에 조건식은 index가 -1 보다 클때까지 반복되는 것으로 설정하고,
index가 -1보다 높으면 arr.splice를 통해 index자리의 요소를 하나 제거한다.
다시 index = arr.indexOf('라') 라는 초기값을 설정하고, while 조건식이 false가 나올 때까지 반복한다.
*/

함수

프로그래밍에서 함수(function)는 특정한 작업을 수행하는 코드를 의미한다.

함수를 미리 만들어 두고 원할 때 실행해 정해진 작업을 수행하게 할 수 있다.

함수를 만들 때는 보통 function 예약어를 사용하거나 =>(화살표) 기호를 사용한다.

화살표 기호를 사용한 함수를 화살표 함수(arrow function)라고 한다.

function( ) { }
// 또는
( ) => { }

함수에 이름을 붙이면 다른 곳에서 사용할 수 있습니다.

function a() {}
const b = function() {};
const c = () => {};

a와 같이 함수를 상수에 대입하지 않고 function 키워드 뒤에 함수 이름을 넣는 방식을 함수 선언문(function declaration statement)이라고 한다.

b, c 처럼 상수나 변수에 대입하는 방식을 함수 표현식(function expression)이라고 한다.

변수와 마찬가지로 함수를 만드는 행위도 선언한다(declare)고 표현한다.

함수의 이름 뒤에는 ( )를 붙입니다. console.log, parseInt도 함수입니다. 

function a() {
  console.log('Hello');
  console.log('Function');
}
a();

/*
Hello
Function
*/

위의 예제처럼 함수 안에 함수를 다시 호출할 수 있습니다. 

실행하려는 코드를 함수로 만들어 놓으면 재사용하기 쉽습니다.

다음 예제처럼 함수 a를 여러 번 호출하면 호출한 만큼 내부의 실행문이 실행됩니다.

function a() {
  console.log('Hello');
  console.log('Function');
}
a();
a();
a();

/*
Hello
Function
Hello
Function
Hello
Function
*/

return 이해하기

함수를 호출하면 항상 결괏값이 나오는데, 기본값으로 undefined가 나옵니다. 이 값을 반환 값(return value)이라고 합니다.

반환 값을 직접 정할 수도 있습니다. return 문을 추가하면 됩니다.

function a() {
  return 10;
}

a(); // 10

반환 값도 값이므로 다른 식이나 문에 넣어 사용할 수 있습니다.

function a() {
  return 10;
}
console.log(a());
// 10

함수의 반환 값을 상수나 변수에 대입할 수도 있습니다. 함수의 반환 값도 값이라는 점을 꼭 기억해야 합니다.

function a() {
  return 10;
}
const b = a();
console.log(b);

// 10

return 문의 또 다른 기능은 함수의 실행을 중간에 멈추는 역할입니다.

function a() {
  console.log('Hello');
  return;
  console.log('Return');
}
a();

// Hello

console.log('Return')보다 return 문이 더 위에 있기 때문에 return 문이 실행되면 그 아래 코드는 아예 실행되지 않습니다.

 

매개변수와 인수 사용하기

function a(parameter) {
  console.log(parameter);
}
a('argument');

// argument

이 문자열은 함수 a를 선언할 때 소괄호에 넣은 parameter와 연결됩니다. 

따라서 parameter는 'argument'의 값을 가집니다. parameter = 'argument'와 같고, 실제로 parameter는 변수와 같은 특성을 가집니다. 함수를 호출할 때 넣은 'argument' 같은 값들은 인수(argument)라고 하고, 함수를 선언할 때 사용한 parameter 같은 변수를 매개변수(parameter)라고 합니다.

 

함수가 하나의 매개변수와 하나의 인수만을 가지는 것은 아닙니다. 각각 여러 개를 가질 수 있고, 매개변수와 인수의 개수가 일치하지 않아도 됩니다.

function a(w, x, y, z) {
  console.log(w, x, y, z);
  console.log(arguments);
}
a('Hello', 'Parameter', 'Argument');

Hello Parameter Argument undefined
Arguments(3) ['Hello', 'Parameter', 'Argument']

인수 Hello, Parameter, Argument가 각각 매개변수 w, x, y에 연결됩니다. 이때 대응되지 않는 매개변수에는 자동으로 undefined 값이 대입됩니다. 따라서 매개변수 z의 값이 undefined가 됩니다.

그런데 화살표 함수 안에서는 arguments를 사용할 수 없습니다. arguments는 function으로 선언한 함수에서만 사용할 수 있습니다.

function add(x, y) {
  return x + y;
}
console.log(add(3,5)); // 8
console.log(add(8,7)); // 15

첫 호출 시에는 인수로 받은 3, 5가 매개변수 x, y에 연결됐습니다. 그 후 return 문을 통해 이 둘을 더한 값을 반환합니다. 다음 호출도 마찬가지입니다.

1분 퀴즈
매개변수로 x, y, z를 받아 곱한 값을 반환하는 multiply 함수를 만들어 보세요. 단, 화살표 함수로 만드세요.

정답 및 해설

const multiply (x,y,z) => {
  return x * y * z;
}

// multiply 함수를 const로 선언 매개변수 값에 x,y,z를 넣고 return 값에 x,y,z 각각 곱하는 식 대입

 

다른 변수 사용하기

함수 안에서 변수나 상수를 선언할 수도 있습니다. 또한, 함수 바깥에 위치한 변수나 상수를 사용할 수도 있습니다.

function minus1(x, y) {
  const a = 100;
  return (x - y) * a;
}
console.log(minus1(5, 3));

// 200


const a = 100;
function minus2(x, y) {
  return (x - y) * a;
}
console.log(minus1(5, 3));

// 200

이렇게 함수는 자신의 매개변수나 내부에 선언한 상수나 변수가 아니더라도 다른 상수와 변수에 접근할 수 있습니다. 다만, 모든 상수나 변수에 접근할 수는 없고 스코프에 따라 접근 가능 여부가 달라집니다.

minus1 함수처럼 자신의 매개변수나 내부 변수(또는 상수)만 사용하는 함수를 순수 함수라고 부르고, minus2 함수는 외부 변수(또는 상수)에 접근하고 있으므로 순수 함수가 아닙니다.

 

객체 리터럴

객체는 여러 개의 변수를 하나의 변수로 묶을 때 사용합니다. 

const information = {
  name: '홍길동',
  year: 2022,
  month: 6,
  date: 23,
  gender: 'M',
};

information이라는 변수를 선언해 그 안에 정보를 모아 두었습니다. 정보들은 { } 안에 묶여 있습니다.

객체 내부에 사용되는 name, year, month, date, gender 같은 정보들은 속성(property)이라고 합니다.

속성은 속성 이름과 속성 값으로 구분됩니다. 속성 값은 각 속성에 들어가 있는 값을 말합니다.

이처럼 { }를 사용해 객체를 표현하는 것을 객체 리터럴 이라고 합니다.

속성 이름은 문자열이어야 하고, 속성 값은 자바스크립트의 모든 값이 들어갈 수 있습니다.

console.log(information.name);
console.log(information['name']);

속성에 접근하는 방법은 두 가지 입니다. 온점(.)을 통해 접근하는 방법과, 배열처럼 [ ] 를 사용해 접근하는 방법입니다.

대부분은 [ ] 보다 온점(. )을 통해 접근하지만,, 온점을 사용할 수 없는 경우도 있습니다.

대표적으로 속성 이름에 띄어쓰기나 온점이 들어가 있는 경우에 그렇습니다.

이럴 때는 변수['속성 이름'] 또는 변수 ['속성.이름']처럼 [ ] 를 사용해서 접근해야 합니다.

객체 속성 수정하기

information.name = '이순신';

변수.속성 = 값;을 하면 주어진 값으로 속성 값이 바뀝니다.

 

객체 속성 제거하기

delete information.name;

delete 변수. 속성;을 하면 해당 속성이 제거됩니다. 이때 제거된 속성 값은 undefined가 됩니다.

 

배열과 함수가 객체인 이유

배열과 함수가 객체인 이유는 객체의 성질을 모두 다 사용할 수 있기 때문입니다.

배열과 함수에도 속성들을 추가하거나 수정 및 제거할 수도 있습니다. 객체는 함수와 배열을 포함하는 개념이라서 { }를 사용해 만든 객체를 객체 리터럴이라고 따로 부르는 것입니다.

function hello() {}
hello.a = 'really?';
const array = [];
array.b 'wow!';
console.log(hello.a);
console.log(array.b);

// really?
// wow!

다만, 함수와 배열은 주로 객체 리터럴과는 다른 목적으로 사용하기에 함수와 배열에 임의 속성을 넣는 경우는 드뭅니다. 임의 속성을 넣고자 한다면 처음부터 객체 리터럴을 사용하지 함수와 배열을 사용할 이유가 없습니다.

 

메서드 이해하기

속성 값으로 자바스크립트의 모든 값을 넣을 수 있습니다.

문자열, 숫자, 불 값, null, undefined 그리고 함수, 배열, 다른 객체까지도 넣을 수 있습니다.

객체의 속성 값으로 함수가 들어가면 이 속성을 특별히 메서드(method)라고 합니다.

const debug = {
  log: function(value) {
    console.log(value);
  },
};
debug.log('Hello, Method');

logsms debug 객체의 메서드입니다. 지금까지 콘솔 창에 결과를 출력하려고 사용했던 함수가 바로 console 객체의 log 메서드였습니다. console 객체와 그 안에 든 log 메서드는 웹 브라우저가 기본으로 만들어 놓은 객체이므로 따로 선언하지 않아도 사용할 수 있습니다.

 

객체 간 비교하기

{} === {};

// false

객체가 아닌 숫자, 문자열, 불 값, null, undefined는 모두 true를 반환합니다.

'str' === 'str';
123 === 123;
false === false;
null === null;
underfined === underfined;

// true

객체는 모양이 같아도 생성할 때마다 새로운 객체가 생성된다. 따라서 같은 객체인지 비교하려면 기존 객체를 변수에 저장해 두어야 한다.

const a = {name: '홍길동'};
const array = [1, 2, a];
console.log(a === array[2]);

// true

참조와 복사

객체를 사용할 때 반드시 알아야 하는 개념이 참조(reference)입니다.

const a = {name: '홍길동'};
const b = a;
a.name = 'hero';
console.log(b.name);

// hero

변수 a에 b를 대입한 상황입니다. a 변수의 name 속성 값을 변경했는데, b 변수도 같이 변경됐습니다.

객체를 저장한 변수를 다른 변수에 대입하면 두 변수 모두 같은 객체를 저장하는 셈이 됩니다.

 a와 b 변수 모두 같은 객체를 저장하고 있는 것이므로 객체의 속성 값을 바꾸면 변수 a와 b 모두 바뀌는 것처럼 보입니다.

이러한 상황일 때 변수 a와 b가 같은 객체를 참조하고 있다고 표현합니다.

또는 a와 b 그리고 객체 간에 참조 관계가 있다고 표현합니다.

다만, 객체가 아닌 값(문자열, 숫자, 불 값, null, underfiend)의 경우는 조금 다릅니다.

let a = '홍길동';
let b = a;
a = 'hero';
console.log(b);

// 홍길동

a 값을 바꿨는데도 b의 값은 바뀌지 않았습니다.

이렇게 참조가 생기지 않는 상황을 복사(copy)라고 합니다.

1분 퀴즈
다음과 같이 객체 안에 객체가 있을 때, '조' 값에 접근하는 방법은 무엇일까요?
const zerocho = {
  name: {
    first: '현영',
    last: '조'.
  },
    gender: 'm',
};

정답 및 풀이

zerocho.name.last;
zerocho['name']['last'];
반응형
Comments