Study/JavaScript

제로초 JavaScript 강의 - 매개변수와 인수, 객체 리터럴 기본, 객체 간의 비교

posey 2023. 2. 20. 10:06

 

  • 제로초 JavaScript 강의 - 매개변수와 인수, 객체 리터럴 기본, 객체 간의 비교



Review

 

 

 

 

 

 


 

  • 제로초 JavaScript 강의 - 매개변수와 인수, 객체 리터럴 기본, 객체 간의 비교

 

 

<매개변수와 인수 사용하기>

 

: console.log 함수를 호출할 때 소괄호 안에 값을 넣는다.

그렇게 넣은 값을 console.log 함수가 받아서 콘솔에 출력한다. 여기서 알 수 있는 것은 함수에

원하는 값을 넣을 수도 있다는 것이다. 여기서 매개변수와 인수의 관계가 나온다.

 

> function a(parameter) {  // 선언시 파라미터 혹은 매개변수
    console.log(parameter);
  }
  a('argument');  // 호출시 argument 혹은 인수

  argument

 

이 예제를 이해하려면 함수 a 호출 시 소괄호에 넣은 '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에 연결된다. 그런데 매개변수 z

대응되는 인수는 존재하지 않는다. 이때 대응되지 않는 매개변수에는 자동으로 undefined 값이

대입된다. 따라서 매개변수 z의 값이 undefined가 된다.

 

이렇게 매개변수와 인수의 개수가 일치하지 않을 수 있다. 따라서 매개변수의 개수로 인수의

개수를 추정할 수 없다.

만약 인수가 몇 개 들어왔는지 궁금하다면 어떻게 해야 할까?

함수 내에서 arguments라는 값을 사용할 수 있다. 예제에서 console.log(arguments) arguments

출력해 보니 호출 시 넣었던 인수 목록을 볼 수 있다. 그 뒤에 나오는 callee Symbol(Symbol.iterator)

인수가 아니므로 무시해도 된다.

그런데 화살표 함수 안에서는 arguments를 사용할 수 없다는 점을 기억하자. 

arguments는 function으로 선언한 함수에서만 사용할 수 있다.

 

 

대응되지 않는 매개변수는 undefined가 된다. 고로 매개변수 y의 값은 undefined가 된다.

숫자 + undefinedNaN이 반환된다.

 

 

이번에는 인수는 같지만 매개변수의 개수를 인수보다 적게 만들어 보겠다.

 

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

  Hello Parameter

예제를 실행하면 Hello w에 대응되고, Parameter x에 대응된다.

남은 Argument는 어떠한 매개변수에도 대응되지 않는다. 이때 Argument는 사용되지 않는다.

 

더하기를 하는 간단한 함수를 만들어 보겠다.

 

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

  8
  15

 

첫 호출 시에는 인수로 받은 3, 5가 매개변수 x, y에 연결됐다. 그 후 return 문을 통해 이 둘을

더한 값(8)을 반환한다. 다음 호출 시에는 인수로 8 7을 받았습니다.

역시 return 문을 통해 이 둘을 더한 값(15)을 반환한다.

 

이렇게 한번 더하기 함수를 만들면 인수만 바꿔 가면서 더하기 함수를 재사용할 수 있다.

지금은 함수가 너무 간단해서 직접 3 + 5나 8 + 7을 하는 것이 더 간단하지만, 수학식이나 기능이

복잡해지면 함수의 유용함을 깨닫게 될 것이다.

 

 

 

<1분 퀴즈>

매개변수로 x, y, z을 받아 곱한 값을 반환하는 multiply 함수를 만들어 보세요.

단, 화살표 함수로 만드세요.

 

정답

 

 

화살표 함수의 특징은 중괄호와 return이 이어지면 중괄호와 return을 생략할 수 있다는 것이다.

 

const f = (x, y, z) => x * y * z;

 

그래서 위의 코드를 이런 식으로도 나타낼 수 있다.

 

 

 

 

<다른 변수 사용하기>

 

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

수도 있다.

 

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

  200

 

함수 안에서 상수 a를 선언한 후 return 문에서 사용했다. 이처럼 함수 안에 새로운 변수나 상수를

선언해도 된다.

 

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

  200

 

실행결과는 같지만, 코드가 조금 다르다. 이번에는 상수 a가 함수를 선언하기 전에 이미 선언되어

있다. 이렇게 함수는 자신의 매개변수나 내부에 선언한 상수나 변수가 아니더라도 다른 상수와 변수에

접근할 수 있다. 다만, 모든 상수나 변수에 접근할 수는 없고 스코프(6.6 var와 let의 차이 이해하기에서

배움)에 따라 접근 가능 여부가 달라진다.

 

minus1 함수처럼 자신의 매개변수나 내부 변수(또는 상수)만 사용하는 함수를 순수 함수라고 부른다.

minus2 함수는 외부 변수(또는 상수)에 접근하고 있으므로 순수 함수가 아니다.

 

 

 


 

 

<객체 리터럴>

 

: 배열도 객체고 함수도 객체에 해당하는데, 객체 리터럴은 배열이나 함수가 아닌 것들 중에서

특정 모양을 가지는 것을 말한다. 

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

 

다음과 같이 사람의 정보를 나타내는 변수들이 있다고 가정해보자.

 

const name = '조현영';
const year = 1994;
const month = 8;
const date = 12;
const gender = 'M';

 

언뜻 보기에는 문제가 없는 것 같지만, 다른 사람의 정보를 추가로 표현하고 싶을 때는 문제가 된다.

이미 name, year, month, date, gender 변수를 선언했으므로 다른 사람을 표현할 때 이 변수들을 사용할

수 없다. 이럴 때 객체를 사용하면 여러 개의 변수를 하나로 묶을 수 있다.

 

const zerocho = {
  name: '조현영',
  year: 1994,
  month: 8,
  date: 12,
  gender: 'M',
};

 

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

 

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

속성속성 이름속성 값으로 구분된다. name: '조현영'이란 속성에서는 name이 속성 이름이고,

'조현영'은 속성 값이 된다.

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

 

객체 리터럴 방식으로 객체를 표현하는 것 외에도 다양한 방법으로 객체를 만들 수 있지만, 여기서는

객체 리터럴 방식과 클래스만 사용한다. 클래스는 후에 실전 예제를 만들어 보면서 다루도록 하겠다.

 

 

객체는 다음과 같은 형식으로 구성된다.

 

const 객체 = {
  속성이름: 속성값,
}

 

속성이 여러 개 있다면 쉼표(,)로 구분하면 된다.

 

const 객체 = {
  속성1이름: 속성1값,
  속성2이름: 속성2값,
  속성3이름: 속성3값,
}

 

 

* 제로초의 조언

 

: 앞 예제에서 객체의 속성이 하나이든 여러 개이든 마지막 속성에도 끝에 쉼표를 넣었다.

사실 마지막 속성에는 쉼표를 넣지 않아도 된다. 다만, 편의상의 이유로 쉼표를 넣고 있다.

요즘은 코딩할 때 어떤 코드를 변경했는지 체크해 주는 git 같은 도구를 사용한다. 보통 이러한 종류의

도구는 줄 단위로 어떤 줄이 변경됐는지를 알려 준다.

 

다음과 같이 쉼표를 사용하지 않았다고 해보자.

 

const 객체 = {
  속성이름: 속성값
}

 

이때 다음 속성을 추가하면 기존 속성 뒤에 쉼표를 하나 추가로 넣어야 한다.

 

const 객체 = {
  속성이름: 속성값,
  속성2이름: 속성2값
}

 

추가한 쉼표 하나 때문에 git 같은 도구는 2개 줄이 변경됐다고 표시한다. 속성 하나를 추가했어도

2개 줄이 변경됐다고 표시되는 것이다. 그런데 쉼표 자체는 큰 의미가 있는 문자가 아니다.

이것이 거슬리는 사람들은 쉼표를 속성 끝에 붙이는 것이 좋다.

 

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

변수를 통해 객체의 속성에 접근할 수 있다. 정확히 말하면 객체의 속성 이름을 통해 속성 값에

접근하는 것이다. 

 

zerocho name 속성과 date 속성에 접근해 보겠다.

 

> const zerocho = {
    name: '조현영',
    year: 1994,
    month: 8,
    date: 12,
    gender: 'M',
  };

  console.log(zerocho.name);
  console.log(zerocho['name']);
  console.log(zerocho.date);
  console.log(zerocho['date']);

  조현영
  조현영
  12
  12

 

속성에 접근하는 방법은 두 가지다.

먼저 온점(.)을 통해 접근할 수 있다. 변수.속성으로 접근하면 된다.

또는 배열처럼 [ ]를 사용해 변수[속성]과 같이 접근할 수 있습니다. 이때는 [] 내부에 문자열을 넣어야

한다. 즉, zerocho[name] 하면 안 되고, zerocho['name'] 해야 한다. 

zerocho[name] 하게 되면 name 자리에 name 변수의 값을 사용하게 된다. 

 

참고로 zerocho.hello처럼 zerocho 객체 내부에 존재하지 않는 속성에 접근한다면 undefined가 나온다.

 

> const name = 'date';
  console.log(zerocho['name']);
  console.log(zerocho[name]); // zerocho['date']와 같음
  console.log(zerocho.hello);

  조현영
  12
  undefined

 

대부분은 [ ]보다 온점을 사용해 속성에 접근하지만, 온점을 사용할 수 없는 경우도 있다.

대표적으로 속성 이름에 띄어쓰기나 온점이 들어 있을 때에 그렇다.

속성 이름은 문자열이므로 띄어쓰기와 온점이 들어갈 수 있다. 이럴 때는 변수['속성 이름'] 또는 

변수['속성.이름']처럼 [ ]를 사용해야만 속성에 접근할 수 있다.

 

 

 

 

<객체 속성 수정하기>

 

: 수정하는 방식은 배열에서 요소를 수정하는 것과 비슷하다.

 

> zerocho.gender = 'F';
  console.log(zerocho.gender);

  F

 

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

 

 

 

 

<객체 속성 제거하기>

 

: 객체 내부의 속성을 제거할 수 있다.

> delete zerocho.gender;
  console.log(zerocho.gender);

  undefined

 

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

 

 

 

NOTE  배열과 함수가 객체인 이유

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

배열과 함수에도 속성들을 추가하거나 수정 및 제거할 수도 있다. 객체는 함수와 배열을 포함하는

개념이라서{ }를 사용해 만든 객체객체 리터럴이라고 따로 부르는 것이다.

 

> 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');

 

logdebug 객체의 메서드이다.

이와 비슷한 코드는 바로 console.log이다.

지금까지 콘솔 창에 결과를 출력하려고 사용했던 함수가 바로 console 객체의 log 메서드였다. 

console 객체와 그 안에 든 log 메서드는 웹 브라우저가 기본으로 만들어 놓은 객체이므로 따로

선언하지 않아도 사용할 수 있다.

 

 

 


 

 

<객체 간 비교하기>

 

: 객체를 다룰 때 실수를 가장 많이 하는 상황이 있다. 바로 객체 사이에 비교 연산을 할 때이다.

 

> {} === {}

  false

 

객체끼리는 모양이 같아도 비교를 하면 항상 false를 반환한다.

 

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

 

'str' === 'str';
123 === 123;
false === false;
null === null;
undefined === undefined;

 

객체는 모양이 같아도 생성할 때마다 새로운 객체가 생성된다. 따라서 같은 객체인지 비교하려면

기존 객체를 변수에 저장해 두어야 한다.

 

> const a = { name: 'zerocho' };  // 객체 리터럴
  const array = [1, 2, a];  // 배열 리터럴
  console.log(a === array[2]);

  true

 

 

 

 

 

<참조와 복사>

 

: 객체를 사용할 때 반드시 알아야 하는 개념이 있는데, 바로 참조(reference)다. 

 

> const a = { name: 'zerocho' };
  const b = a;
  a.name = 'hero';
  console.log(b.name);

  hero

변수 b a를 대입한 상황이다.

a 변수의 name 속성 값을 변경했는데, b 변수도 같이 변경됐다. 객체를 저장한 변수를 다른 변수에

대입하면 두 변수 모두 같은 객체를 저장하는 셈이 된다.

a b 변수 모두 같은 객체를 저장하고 있는 것이므로 객체의 속성 값을 바꾸면 변수 a b 모두

바뀌는 것처럼 보인다. 이러한 상황일 때 변수 a b가 같은 객체를 참조하고 있다고 표현한다.

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

 

다만, 객체가 아닌 값(문자열, 숫자, 불 값, null, undefined)의 경우, 즉 원시값들은 조금 다르다.

 

> let a = 'zerocho';
  let b = a;
  a = 'hero';
  console.log(b);

  zerocho

 

이전 예제와 같이 변수 b a를 대입했다. 하지만 a를 바꿨는데도 b는 영향을 받지 않는다.

객체가 아닌 값을 변수에 저장한 경우에는 참조 관계가 생기지 않기 때문다.

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

 

객체를 변수에 담으면 참조 관계가 생김을 기억하자 !

 

 

<1분 퀴즈>

다음과 같이 객체 안에 객체가 있을 때, '조' 값에 접근하는 방법은 무엇일까요?

 

const zerocho = {
  name: {
    first: '현영',
    last: '조',
  },
  gender: 'm',
};

 

// 정답
zerocho.name.last;
zerocho['name']['last'];
반응형