이번에는 함수의 기본 파라미터를 설정하는 방법에 대해서 알아보자.

한번 우리가 원의 넓이를 구하는 함수를 만들어 보겠다.

function calculateCircleArea(r) {
  return Math.PI * r * r;
}

const area = calculateCircleArea(4);
console.log(area); // 50.26548245743669

여기서 Math.PI는 원주율 파이 값을 가르킵니다.

만약 우리가 이 함수에 r값을 넣어주지 않으면 어떤 결과가 나타 날까?

function calculateCircleArea(r) {
  return Math.PI * r * r;
}

const area = calculateCircleArea();
console.log(area); // NaN

결과는 NaN이 나온다. Not a Number 라는 의미로, 우리가 undefined*undefined이렇게 숫자가 아닌 값에 곱셈을 하니까 이상한 결과물이 나왔다.

 

이 함수에서 만약에 r값이 주어지지 않았다면 기본 값을 1을 사용 하도록 설정해 보자.

 

우리가 지금 까지 배운 것들을 활용하면 이렇게 작성 할수 있다.

function calculateCircleArea(r) {
  const radius = r || 1;
  return Math.PI * radius * radius;
}

const area = calculateCircleArea();
console.log(area); // 3.141592653589793

ES5 시절엔 위와 같이 하는게 최선이였는데, ES6 에선 다음과 같이 할 수 있게 되었다

function calculateCircleArea(r = 1) {
  return Math.PI * r * r;
}

const area = calculateCircleArea();
console.log(area); // 3.141592653589793

함수의 기본 파라미터 문법은 화살표 함수에서도 사용 할 수 있다.

const calculateCircleArea = (r = 1) => Math.PI * r * r;

const area = calculateCircleArea();
console.log(area); // 3.141592653589793

이번에는 논리 연산자를 조금 더 유용하게 사용하는 방법에 대해서 알아보자

우리가 이전에 연산자를 배울때, 다음과 사항을 잘 숙지했을 것이다.

true && true // true
true && false // false
true || false // true
false || true // true

논리 연산자를 사용 할 떄는 무조건 우리가 true 혹은 false값을 사용 해야 되는 것은 아니다.

문자열이나 숫자, 객체를 사용할 수도 있고, 해당 값이 Truthy하냐 Falsy 하냐에 따라 결과가 달라진다.

예를 들어서 다음과 같은 코드가 있다고 가정해 보자.

const dog = {
  name: '멍멍이'
};

function getName(animal) {
  return animal.name;
}

const name = getName(dog);
console.log(name); // 멍멍이

그런데 만약, getName의 파라미터가 제대로 된 객체가 주어지지 않으면 어떻게 될까?

const dog = {
  name: '멍멍이'
};

function getName(animal) {
  return animal.name;
}

const name = getName();
console.log(name);

animal객체가 undefined 이기 때문에, undefined에서 name값을 조회 할수 없어서 이렇게 에러가 발생하게 된다.

그렇다면 만약 함수에서 animal값이 제대로 주어졌을때만 name을 조회하고, 그렇지 않을때는 그냥 undefined를 반환하게 하고 싶으면 어떻게 해야 할까요?

const dog = {
  name: '멍멍이'
};

function getName(animal) {
  if (animal) {
    return animal.name;
  }
  return undefined;
}

const name = getName();
console.log(name);

이렇게 하면 animal 값이 주어지지 않아도, 에러가 발생하지 않게 된다. 이러한 코드를 논리 연산자를 사용하면 코드를 단축시킬수 있다.

 

&& 연산자로 코드 단축시키기

이렇게 코드를 작성해보자.

const dog = {
  name: '멍멍이'
};

function getName(animal) {
  return animal && animal.name;
}

const name = getName();
console.log(name); // undefined

아까 코드와 이 코드는 완벽히 똑같이 작동하는 코드이다. 다음과 같이 파라미터를 넣어서 호출해보자.

const dog = {
  name: '멍멍이'
};

function getName(animal) {
  return animal && animal.name;
}

const name = getName(dog);
console.log(name); // 멍멍이

이게 작동하는 이유는, A && B 연산자를 사용하게 될 때에는 A가 Truthy한 값이라면, B 가 결과값이 된다. 반면, A가 Falsy한 값이라면 결과는 A가 된다.

다음 예시를 한번 살펴보자.

console.log(true && 'hello'); // hello
console.log(false && 'hello'); // false
console.log('hello' && 'bye'); // bye
console.log(null && 'hello'); // null
console.log(undefined && 'hello'); // undefined
console.log('' && 'hello'); // ''
console.log(0 && 'hello'); // 0
console.log(1 && 'hello'); // hello
console.log(1 && 1); // 1

이러한 속성을 잘 알아두면, 특정 값이 유효할때에만 어떤 값을 조회하는 작업을 해야 할 떄 매우 유용하다.

 

|| 연산자로 코드 단축시키기

 

|| 연산자는 만약 어떤 값이 Falsy 하다면 대체로 사용 할 값을 지정해줄 때 매우 유용하게 사용 할 수 있다.

 

예를 들어서 다음과 같은 코드가 있다고 가정해 본다.

const namelessDog = {
  name: ''
};

function getName(animal) {
  const name = animal && animal.name;
  if (!name) {
    return '이름이 없는 동물입니다';
  }
  return name;
}

const name = getName(namelessDog);
console.log(name); // 이름이 없는 동물입니다.

위 코드는 || 연산자를 사용하면 다음과 같이 단축 시킬수 있다.

const namelessDog = {
  name: ''
};

function getName(animal) {
  const name = animal && animal.name;
  return name || '이름이 없는 동물입니다.';
}

const name = getName(namelessDog);
console.log(name); // 이름이 없는 동물입니다.

A || B 는 만약 A 가 Truthy 할경우 결과는 A 가 된다. 반면 A가 Falsy 하다면 결과는 B가 된다.

 

'공부내용정리 > JavaScript' 카테고리의 다른 글

비구조화 할당 (구조분해) 문법  (0) 2021.04.21
조건문 더 스마트 하게 쓰기  (0) 2021.04.20
Truthy and Falsy  (0) 2021.04.19
삼항 연산자  (0) 2021.04.19
프로토타입과 클래스  (0) 2021.04.18

자바스크립트 문법은 아니지만 알아둬야 하는 개념이다.

Truth : true같은거 Falsy: false같은거 라고 생각하면 된다. 예를 들어 다음과 같은 함수가 있다고 가정해보자.

function print(person) {
  console.log(person.name);
}

const person = {
  name: 'John'
};

print(person);

만약에 이러한 상황에서, print함수가 다음과 같이 파라미터가 비어진 채로 실행됬다고 가정해보자.

function print(person) {
  console.log(person.name);
}

const person = {
  name: 'John'
};

print();

이 코드는 다음과 같은 에러를 생성해낸다.

TypeError: Cannot read property 'name' of undefined

이러한 상황에서, 만약에 print 함수에서 만약에 object가 주어지지 않았다면, 문제가 있다고 콘솔에 출력해야 한다면 다음과 같이 구현할수 있다.

function print(person) {
  if (person === undefined) {
    return;
  }
  console.log(person.name);
}

const person = {
  name: 'John'
};

print();

그런데 만약에 다음과 같이 print에 null값이 파라미터로 전달되면 어떨까?

function print(person) {
  if (person === undefined) {
    console.log('person이 없네요');
    return;
  }
  console.log(person.name);
}

const person = null;
print(person);

그러면 또 오류가 발생하게 된다.

TypeError: Cannot read property 'name' of null

그러면 또 print함수에 조건을 추가해줘야 한다.

function print(person) {
  if (person === undefined || person === null) {
    console.log('person이 없네요');
    return;
  }
  console.log(person.name);
}

const person = null;
print(person);

이와 같이 person이 undefined이거나, null인 상황을 대비하려면 위와같이 코드를 작성해야하는데 여기서 위 코드는 다음과 같이 축약해서 작성할수 있다.

function print(person) {
  if (!person) {
    console.log('person이 없네요');
    return;
  }
  console.log(person.name);
}

const person = null;
print(person);

이게 작동한 이유는 undefined와 null은 Falsy한 값이다. Falsy 한 값 앞에 느낌표를 붙여주면 true로 전환된다.

다음 코드를 입력해보자.

console.log(!undefined);
console.log(!null);

Falsy 한 값은 이 외에도 몇개 더 있다.

console.log(!undefined);
console.log(!null);
console.log(!0);
console.log(!'');
console.log(!NaN);

이 값은 모두 true 가 된다.

여기서NaN이란 값은 생소한데, 이값은 Not A Number라는 의미이다. 보통 NaN은 문자열을 숫자로 변환 하는 자바스크립트 기본 함수 parseInt 라는 함수를 사용하게 될떄 볼수 있다.

const num = parseInt('15', 10); // 10진수 15를 숫자로 변환하겠다는 의미
console.log(num); // 10
const notnum = parseInt('야호~', 10);
console.log(notnum); // NaN

다시 본론으로 돌아와서, Falsy한 값은 아까 나열한 다섯가지 이다.

그리고 그 외의 값은 모두! Truthy한 값이다.

다음 코드를 작성해보자

console.log(!3);
console.log(!'hello');
console.log(!['array?']);
console.log(![]);
console.log(!{ value: 1 });

아까와 반대로 보두 false가 된다

Truthy 한값과 Falsy한 값은 if문에서도 사용 가능하다.

const value = { a: 1 };
if (value) {
  console.log('value 가 Truthy 하네요.');
}

value가 Truthy한 값이기 때문에, 콘솔에 메세지가 출력될 것이다. 반면 value가 null, undefined, 0, '',NaN중 하나라면 나타나지 않을 것이다.

그래서 이렇게 Truthy 한 값과 Falsy한 값을 잘 알아 놓으면 조건문을 작성할때 편할 것이다.

추가적으로 알아두면 좋은 팁!

 

만약에 특정 값이 Truthy한 값이라면 true 그렇지 않다면 false로 값을 표현하는 것울 구현해 보겠다.

const value = { a: 1 };

const truthy = value ? true : false;

 

우리가 이전에 배운 삼항연산자를 사용하면 쉽게 value 값의 존재 유무에 따라 쉽게 true 및 false 로 전환이 가능하다. 그런데 더 쉽게 표현할수도 있다.

const value = { a: 1 };
const truthy = !!value;

!value 는 false 가 되고, 여기에 !false 는 true 가 되어서, 결과는 true 가 된다.

'공부내용정리 > JavaScript' 카테고리의 다른 글

조건문 더 스마트 하게 쓰기  (0) 2021.04.20
단축 평가(short-circuit evaluation)논리 계산법  (0) 2021.04.20
삼항 연산자  (0) 2021.04.19
프로토타입과 클래스  (0) 2021.04.18
배열 내장함수  (0) 2021.04.18

첫번째로 배울 문법은, 삼항 연산자이다.

const array = [];
let text = '';
if (array.length === 0) {
  text = '배열이 비어있습니다.';
} else {
  text = '배열이 비어있지 않습니다.';
}
console.log(text);

예를 들어 위와 같이 특정 조건에 따라 text값이 달라야 하는 상황이 있다고 가정해보자.

그럴 경우에는 다음과 같이 코드를 작성 할수 있다.

const array = [];
let text = array.length === 0 ? '배열이 비어있습니다' : '배열이 비어있지 않습니다.';

console.log(text);

삼항 연산자의 사용법은 다음과 같다.

조건 ? true일때 : false일때

라인의 길이가 너무 길어진다면 다음과 같이 작성하기도 한다.

const array = [];
let text = array.length === 0 
  ? '배열이 비어있습니다' 
  : '배열이 비어있지 않습니다.';

console.log(text);

다음과 같이 삼항 연산자를 충접해서 쓸수도 있다.

const condition1 = false;
const condition2 = false;

const value = condition1 
  ? '와우!' 
  : condition2 
    ? 'blabla' 
    : 'foo';

console.log(value);

가독성이 좋지 않아서 이런 코드는 피하는 것이 좋다. 차라리 if문으로 처리하는게 오히려 코드를 읽기가 쉬워질수도 있다.

'공부내용정리 > JavaScript' 카테고리의 다른 글

단축 평가(short-circuit evaluation)논리 계산법  (0) 2021.04.20
Truthy and Falsy  (0) 2021.04.19
프로토타입과 클래스  (0) 2021.04.18
배열 내장함수  (0) 2021.04.18
반복문  (0) 2021.04.15

객체 생성자

프로토 타입과 클래스에 대해서 알아보기 전에 우선 객체 생성자라는 것을 알아보자.

객체 생성자라는 것을 알아보자. 객체 생성자는 함수를 통해서 새로운 객체를 만들고 그 안에 넣고 싶은 값 혹은 함수들을 구현 할수 있게 해준다.

다음 코드를 입력해 보자.

function Animal(type, name, sound) {
  this.type = type;
  this.name = name;
  this.sound = sound;
  this.say = function() {
    console.log(this.sound);
  };
}

const dog = new Animal('개', '멍멍이', '멍멍');
const cat = new Animal('고양이', '야옹이', '야옹');

dog.say();
cat.say();

결과물은 다음과 같다.

멍멍
야옹

객체 생성자를 사용할떄는 보통 함수의 이름을 대문자로 시작하고, 새로운 객체를 만들 때에는 new키워드를 앞에 붙여주어야 한다.

지금 위 코드를 보면, dog가 가지고 있는 say 함수와 cat이 가지고 있는 수행하는 코드가 똑같음에도 불구하고 객체가 생성될 때마다 함수도 새로 만들어 져서 this say로 설정이 되고 있다.

같은 객체 생성자 함수를 사용하는 경우, 특정 함수 또는 값을 재사용 할 수 있는데 바로 프로토 타입이다.

프로토 타입

프로토타입은 다음과 같이 객체 생성자 함수 아래에 .prototype.[원하는키] = 코드를 입력하여 설정 할수 있다.

function Animal(type, name, sound) {
  this.type = type;
  this.name = name;
  this.sound = sound;
}

Animal.prototype.say = function() {
  console.log(this.sound);
};
Animal.prototype.sharedValue = 1;

const dog = new Animal('개', '멍멍이', '멍멍');
const cat = new Animal('고양이', '야옹이', '야옹');

dog.say();
cat.say();

console.log(dog.sharedValue);
console.log(cat.sharedValue);

결과는 다음과 같다.

멍멍
야옹
1
1

객체 생성자 상속받기

예를 들어서 Cat과 Dog라는 새로운 객체 생성자를 만든다고 가정해보자. 그리고 해당 객체 생성자들에서 Animal의 기능을 재사용 한다고 가정해 보자. 그렇다면, 이렇게 구현할수 있다.

function Animal(type, name, sound) {
  this.type = type;
  this.name = name;
  this.sound = sound;
}

Animal.prototype.say = function() {
  console.log(this.sound);
};
Animal.prototype.sharedValue = 1;

function Dog(name, sound) {
  Animal.call(this, '개', name, sound);
}
Dog.prototype = Animal.prototype;

function Cat(name, sound) {
  Animal.call(this, '고양이', name, sound);
}
Cat.prototype = Animal.prototype;

const dog = new Dog('멍멍이', '멍멍');
const cat = new Cat('야옹이', '야옹');

dog.say();
cat.say();

새로 만든 Dog와 Cat함수에서 Animal.call을 호출해주고 있는데, 여기서 첫번째 인자에서는 this를 넣어주어야 하고, 그이후에는 Anumal객체 생성자 함수에서 필요로 하는 파라미터를 넣어 주어야 한다.

추가적으로 prototype을 공유해야 하기 때문에 상속 받은 객체 생성자 함수를 만들고 나서 prototype값을 Anumal.prototype으로 설정해 주었다.

클래스

클래스라는 기능은 C++, Java, C#, PHP 등의 다른 프로그래밍 언어에있는 기능있데 자바스크립트에는 없었기 때문에 예전 자바스크립트(ES5)에서는 클래스 문법이 따로 없었기 땜누에 위에서 작성한 코드처럼 객체 생성자 함수를 사용하여 비슷한 작업을 구현해 왔다.

ES6에서부터는 class라는 문법이 추가됬는데, 우리가 객체 생성자로 구현했던 코드를 조금 더 명확하고, 깔끔하게 구현 할수 있게 해준다. 추가적으로, 상속도 훨씬 쉽게 해줄 수 있다.

class Animal {
  constructor(type, name, sound) {
    this.type = type;
    this.name = name;
    this.sound = sound;
  }
  say() {
    console.log(this.sound);
  }
}

const dog = new Animal('개', '멍멍이', '멍멍');
const cat = new Animal('고양이', '야옹이', '야옹');

dog.say();
cat.say();

여기서 우리가 say라는 함수를 클래스 내부에 선언하였는데, 클래스 내부의 함수를 메서드라고 부른다. 이렇게 메서드를 만들면 자동으로 prototype으로 등록이 된다.

결과는 다음과 같다.

멍멍
야옹

class를 사용 했을때에는, 다른 클래스를 쉽게 상속 할수 있다.

class Animal {
  constructor(type, name, sound) {
    this.type = type;
    this.name = name;
    this.sound = sound;
  }
  say() {
    console.log(this.sound);
  }
}

class Dog extends Animal {
  constructor(name, sound) {
    super('개', name, sound);
  }
}

class Cat extends Animal {
  constructor(name, sound) {
    super('고양이', name, sound);
  }
}

const dog = new Dog('멍멍이', '멍멍');
const cat = new Cat('야옹이', '야옹');

dog.say();
cat.say();

결과물은 다음과 같다.

멍멍
야옹

상속을 할 때는 extends 키워드를 사용하며, constructor에서 사용하는 super() 함수가 상속받은 클래스의 생성자를 가르킨다.

class Animal {
  constructor(type, name, sound) {
    this.type = type;
    this.name = name;
    this.sound = sound;
  }
}

class Dog extends Animal {
  constructor(name, sound) {
    super('개', name, sound);
  }
}

class Cat extends Animal {
  constructor(name, sound) {
    super('고양이', name, sound);
  }
}

const dog = new Dog('멍멍이', '멍멍');
const dog2 = new Dog('왈왈이', '왈왈');
const cat = new Cat('야옹이', '야옹');
const cat2 = new Cat('냐옹이', '냐옹');

dog.say();
dog2.say();
cat.say();
cat2.say();

연습

연습삼아 다음 클래스도 만들어보자.

class Food {
  constructor(name) {
    this.name = name;
    this.brands = [];
  }
  addBrand(brand) {
    this.brands.push(brand)
  }
  print() {
    console.log(`${this.name}을/를 파는 음식점들:`)
    console.log(this.brands.join(', '));
  }
}

const pizza = new Food('피자');
pizza.addBrand('피자헛');
pizza.addBrand('도미노 피자');

const chicken = new Food('치킨');
chicken.addBrand('굽네치킨');
chicken.addBrand('BBQ');

pizza.print()
chicken.print();

 

'공부내용정리 > JavaScript' 카테고리의 다른 글

Truthy and Falsy  (0) 2021.04.19
삼항 연산자  (0) 2021.04.19
배열 내장함수  (0) 2021.04.18
반복문  (0) 2021.04.15
배열  (0) 2021.04.15

forEach

forEach 는 가장 쉬운 배열 내장 함수이다. 기존에 우리가 배웠던 for문을 대체 시킬수 있다. 예를들어 다음과 같은 텍스트 배열이 있다고 가정해보자.

const superheroes = ['아이언맨', '캡틴 아메리카', '토르', '닥터 스트레인지'];

만약 배열안에 있는 모든 원소들을 모두 출력해야 한다면 for문을 사용하여 다음과 같이 구현할수 있다.

const superheroes = ['아이언맨', '캡틴 아메리카', '토르', '닥터 스트레인지'];

for (let i = 0; i < superheroes.length; i++) {
  console.log(superheroes[i]);
}

배열의 forEach함수를 사용하면 다음과 같이 구현할수 있다.

const superheroes = ['아이언맨', '캡틴 아메리카', '토르', '닥터 스트레인지'];

superheroes.forEach(hero => {
  console.log(hero);
});

forEach함수의 파라미터로는, 각 원소에 대하여 처리하고 싶은 코드를 함수로 넣어준다. 이 함수의 파라미터 hero는 각 원소를 가르키게 된다.

이렇게 함수형태의 파라미터를 전달하는 것을 콜백함수라고 한다. 함수를 등록해주면, forEach가 실행을 해주는 것이다.

map

map은 배열안의 각 원소를 변환 할떄 사용 되며, 이 과정에서 새로운 배열이 만들어진다.

예를 들어서 다음과 같은 배열이 있다고 가정해보자.

const array = [1, 2, 3, 4, 5, 6, 7, 8];

만약에 배열 안의 모든 숫자를 제곱해서 새로운 배열을 만들고 싶다면 어떻게 해야할까? map 함수를 사용하지 않고 우리가 지금까지 배운 지식들을 사용하면 다음과 같이 구현할수 있다.

const array = [1, 2, 3, 4, 5, 6, 7, 8];

const squared = [];
for (let i = 0; i < array.length; i++) {
  squared.push(array[i] * array[i]);
}

console.log(squared);

또는 방금 배운 forEach 를 쓰면 다음과 같이 구현할수도 있다.

const array = [1, 2, 3, 4, 5, 6, 7, 8];

const squared = [];

array.forEach(n => {
  squared.push(n * n);
});

console.log(squared);

결과는 다음과 같다.

[1, 4, 9, 16, 25, 36, 49, 64];

만약 map을 사용하면 이를 더 짧은 코드를 사용하여 구현할수 있다.

const array = [1, 2, 3, 4, 5, 6, 7, 8];

const square = n => n * n;
const squared = array.map(square);
console.log(squared);

map함수의 파라미터로는 변화를 주는 함수를 전달해 준다. 이를 변화함수라고 부르도록 하겠다.

현재 우리의 변화함수 square는 파라미터 n을 받아와서 이를 제곱해 준다.

array map함수를 사용 할때 square를 변화함수로 사용함으로서, 내부의 모든 값에 대하여 제곱을 해서 새로운 배열을 생성하였다.

변화 함수를 꼭 이름을 붙여서 선언 할 필요는 없다. 코드를 다음과 같이 작성해도 된다.

const squared = array.map(n => n * n);
console.log(squared);

indexOf

indexOf는 원하는 항목이 몇번째 원소인지 찾아주는 함수이다.

예를 들어 다음과 같은 배열이 있을 때,

const superheroes = ['아이언맨', '캡틴 아메리카', '토르', '닥터 스트레인지'];

토르가 몇번째 항목인지 알고 싶다고 가정해보자.

그렇다면 이렇게 입력할수 있다.

const superheroes = ['아이언맨', '캡틴 아메리카', '토르', '닥터 스트레인지'];
const index = superheroes.indexOf('토르');
console.log(index);

결과는 2가 나타난다.

index값은 0부터 시작하기 때문에  0: 아이언맨 1: 캡틴 아메리카 2: 토르 이렇게 되서 2라는 값이 나타나는 것이다.

findIndex

만약에 배열 안에 있는 값이 숫자, 문자열, 또는 불리언이라면 찾고자 하는 항목이 몇번째 원소인지 알아내려면 indexOf를 사용하면 된다. 하지만, 배열 안에 있는 값이 객체이거나, 배열이라면 indexOf로 찾을수 없다.

예를 들어서 다음과 같은 배열이 있다고 가정해보자.

const todos = [
  {
    id: 1,
    text: '자바스크립트 입문',
    done: true
  },
  {
    id: 2,
    text: '함수 배우기',
    done: true
  },
  {
    id: 3,
    text: '객체와 배열 배우기',
    done: true
  },
  {
    id: 4,
    text: '배열 내장함수 배우기',
    done: false
  }
];

여기서 만약 id가 3인 객체가 몇번째인지 찾으려면, findIndex함수에 검사하고자 하는 조건을 반환하는 함수를 넣어서 찾을수 있다.

const todos = [
  {
    id: 1,
    text: '자바스크립트 입문',
    done: true
  },
  {
    id: 2,
    text: '함수 배우기',
    done: true
  },
  {
    id: 3,
    text: '객체와 배열 배우기',
    done: true
  },
  {
    id: 4,
    text: '배열 내장함수 배우기',
    done: false
  }
];

const index = todos.findIndex(todo => todo.id === 3);
console.log(index);

결과는 2가 나온다.

 

find

find함수는 findIndex랑 비슷한데, 찾아낸 값이 몇번쨰인지 알아내는 것이 아니라, 찾아낸 값 자체를 반환한다.

const todos = [
  {
    id: 1,
    text: '자바스크립트 입문',
    done: true
  },
  {
    id: 2,
    text: '함수 배우기',
    done: true
  },
  {
    id: 3,
    text: '객체와 배열 배우기',
    done: true
  },
  {
    id: 4,
    text: '배열 내장함수 배우기',
    done: false
  }
];

const todo = todos.find(todo => todo.id === 3);
console.log(todo);

결과는 다음과 같다

{id: 3, text: "객체와 배열 배우기", done: true}

filter

filter함수는 배열에서 특정 조건을 만족하는 값들만 따로 추출하여 새로운 배열은 만든다. 예를 들어서 방금 만들었던 todos배열에서 done값이 false인 항목들만 따로 추출해서 새로운 배열을 만들어 보자.

const todos = [
  {
    id: 1,
    text: '자바스크립트 입문',
    done: true
  },
  {
    id: 2,
    text: '함수 배우기',
    done: true
  },
  {
    id: 3,
    text: '객체와 배열 배우기',
    done: true
  },
  {
    id: 4,
    text: '배열 내장함수 배우기',
    done: false
  }
];

const tasksNotDone = todos.filter(todo => todo.done === false);
console.log(tasksNotDone);

결과는 다음과 같다.

[
  {
    id: 4,
    text: '배열 내장 함수 배우기',
    done: false
  }
];

filter함수에 넣는 파라미터는 조건을 검사하는 함수를 넣어주며, 이함수의 파라미터로 각 원소의 값을 받아오게 된다.

방금 우리가 작성한 코드는 이렇게 입력할수도 있다.

const tasksNotDone = todos.filter(todo => !todo.done);

filter에 넣어준 함수에서true를 반환하면 새로운 배열에 따로 추출을 해주는데 만약 todo.done값이 false라면, !false가 되고 이 값은 true이기 때문에, 이전의 todo.tone===false와 똑같이 작동하게 된다.

splice

splice는 배열에서 특정 항목을 제거할때 사용한다.

const numbers = [10, 20, 30, 40];

위 배열에서 30을 지운다고 가정해보자. 그러면, 30이 몇번째 index인지 알아낸 이후, 이를 splice를 통해 지워줄수 있다.

const numbers = [10, 20, 30, 40];
const index = numbers.indexOf(30);
numbers.splice(index, 1);
console.log(numbers);

결과는 다음과 같다.

[10, 20, 40]

shift와 pop

shift와 pop은 비슷하지만, 다르다.

shift는 첫번째 원소를 배열에서 추출해준다.(추출하는 과정에서 배열에서 해당 원소는 사라진다.)

const numbers = [10, 20, 30, 40];
const value = numbers.shift();
console.log(value);
console.log(numbers);

결과는 다음과 같다.

10
[20, 30, 40]

이번엔 pop을 해보자

const numbers = [10, 20, 30, 40];
const value = numbers.pop();
console.log(value);
console.log(numbers);

결과는 다음과 같다.

40
[10, 20, 30]

pop은 push의 반대로 생각하면 된다. push는 배열의 맨 마지막에 새 항목을 추가하고, pop은 맨 마지막 항목을 추출한다.

unshift

unshift는 shift의 반대이다.

배열의 맨앞에 새 원소를 추가한다.

const numbers = [10, 20, 30, 40];
numbers.unshift(5);
console.log(numbers);

결과는 다음과 같다.

[5, 10, 20, 30, 40]

concat

concat은 여러개의 배열을 하나의 배열로 합쳐준다.

const arr1 = [1, 2, 3];
const arr2 = [4, 5, 6];
const concated = arr1.concat(arr2);

console.log(concated);

결과는 다음과 같다.

[1, 2, 3, 4, 5, 6];

concat함수는 arr1과 arr2에 변화를 주지 않는다.

join

join은 배열안의 값들을 문자열 형태로 합쳐준다.

const array = [1, 2, 3, 4, 5];
console.log(array.join()); // 1,2,3,4,5
console.log(array.join(' ')); // 1 2 3 4 5
console.log(array.join(', ')); // 1, 2, 3, 4, 5

reduce

reduce함수는 잘 사용 할줄 알면 정말 유용한 내장함수이다.

만약 주어진 배열에 대하여 총합을 구해야 되는 상황이 왔다고 가정해보자

이렇게 구현할수 있을 것이다.

const numbers = [1, 2, 3, 4, 5];

let sum = 0;
numbers.forEach(n => {
  sum += n;
});
console.log(sum);

결과는 15가 된다

여기서 sum을 계산하기 위해서 사전에 sum을 선언하고, forEach를 통해서 계속해서 덧셈을 해주었다.

reduce라는 함수를 사용하면 다음과 같이 구현 할수 있다.

const numbers = [1, 2, 3, 4, 5];
let sum = array.reduce((accumulator, current) => accumulator + current, 0);

console.log(sum);

reduce함수에는 두개의 파라미터를 전달한다. 첫번째 파라미터는 accumulator와 current를 파라미터로 가져와서 결과를 반환하는 콜백함수이고, 두번째 파라미터는 reude함수에서 사용할 초깃값이다.

여기서 accumulator는 누적된 값을 의미한다.

방금 작성한 함수를 다음과 같이 수정해보자.

const numbers = [1, 2, 3, 4, 5];
let sum = numbers.reduce((accumulator, current) => {
  console.log({ accumulator, current });
  return accumulator + current;
}, 0);

console.log(sum);

이 코드의 실행 결과는 다음과 같다.

배열을 처음부터 끝까지 반복하면서 우리가 전달한 콜백함수가 호출이 되는데, 가장 처음엔 accmulator값이 0이다. 이 값이 0인 이유는 우리가 두번째 파라미터인 초깃값으로 0을 설정 했기 때문이다.

처음 콜백 함수가 호출되면, 0+1을 해서 1이 반환된다. 이렇게 1이 반환되면 그 다음 번에 콜백함수가 호출 될떄 accumulator값으로 사용된다.

콜백 함수가두번째로 호출 될 땐 1 + 2 를 해서 3이 되고, 이 값이 세번쨰로 호출될 때의 accumulator가 된다.

그래서 쭉 누적돼서 결과물 15가 나타나는 것이다.

reduce를 사용해서 평균도 계산 할수 있다. 평균을 계산 하려면, 가장 마지막 숫자를 더하고나서 배열의 length로 나누어 주어야 한다.

const numbers = [1, 2, 3, 4, 5];
let sum = numbers.reduce((accumulator, current, index, array) => {
  if (index === array.length - 1) {
    return (accumulator + current) / array.length;
  }
  return accumulator + current;
}, 0);

console.log(sum);

결과를 3이 된다.

위 코드의 reduce에서 사용한 콜백 함수에서는 추가 파라미터로 index와 array를 받아 왔다. index는 현제 처리하고 있는 항목이 몇번째 인지 가르키고, array는 현재 처리하고 있는 배열 자신을 의미한다.

'공부내용정리 > JavaScript' 카테고리의 다른 글

삼항 연산자  (0) 2021.04.19
프로토타입과 클래스  (0) 2021.04.18
반복문  (0) 2021.04.15
배열  (0) 2021.04.15
객체  (0) 2021.04.14

반복문은 특정 작업을 반복적으로 할때 사용할 수 있는 구문이다.

for

for문은 가장 기본적인 반복문이다. 특정 값에 변화를 주어가면서 우리가 정한 조건이 만족된다면 계속 반복한다.

for (let i = 0; i < 10; i++) {
  console.log(i);
}

결과가 0부터 9까지 잘나타났다

for문을 다음과 같이 사용한다.

for (초기 구문; 조건 구문; 변화 구문;) {
  코드
}

for문을 사용할때 보통 i++를 해서 1씩 증감하는 형태로 사용한다. 그런데 1씩 빼는 형태도 가능하다. 다음 코드를 한번 실행해보자.

for (let i = 10; i > 0; i--) {
  console.log(i);
}

1부터 10까지 잘 나타났다.

for문은 이렇게 숫자에 변화를 주어가면서 반복적으로 작업을 실행한다.

배열과 for

이번에는 우리가 이전에 배운 배열과 for문을 함께 활용해 보자.

const names = ['멍멍이', '야옹이', '멍뭉이'];

for (let i = 0; i < names.length; i++) {
  console.log(names[i]);
}

이렇게 하면 names배열안에 있는 원소들을 하나하나 나열할수 있다.

while

while문은 특정 조건이 참이라면 계속해서 반복하는 반복문 이다. for문은 특정 숫자를 가지고 숫자의 값을 비교하고, 증감해주면서 반복을 한다면, while문은 조건을 확인만 하면서 반복을 한다. 때문에 조건문 내부에서 변화를 직접 줘야된다.

우리가 가장 처음 작성했던 0부터 9까지 콘솔에 출력을하는 반복문을 while문으로 구현해보자.

let i = 0;
while (i < 10) {
  console.log(i);
  i++;
}

while문을 사용할떄는 조건문이 언젠간 false가 되도록 신경 써야한다. 만약에 언젠간 false로 전환이 되지 않는다면 반복문이 끝나지 않고 영원히 반복된다.

 

for...of

for...of문은 배열에 관한 반복문을 돌리기 위해서 만들어진 반복문이다.

let numbers = [10, 20, 30, 40, 50];
for (let number of numbers) {
  console.log(number);
}

객체를 위한 반복문 for...in

객체를 위한 반복문을 알아보기 전에, 객체의 정보를 배열 형태로 받아올 수 있는 함수 몇가지를 알아보자.

const doggy = {
  name: '멍멍이',
  sound: '멍멍',
  age: 2
};

console.log(Object.entries(doggy));
console.log(Object.keys(doggy));
console.log(Object.values(doggy));

각 함수의 역할은 다음과 같다.

  • Object.entries : [[키, 값], [키, 값]] 형태의 배열로 변환
  • Object.keys : [키,키,키] 형태의 배열로 변환
  • Object.values:[값, 값, 값] 형태의 배열로 변환

객체가 지니고 있는 값에 대하여 반복을 하고 싶다면 위 함수들을 사용해도 되고, for...in구문을 사용해도 된다.

const doggy = {
  name: '멍멍이',
  sound: '멍멍',
  age: 2
};

for (let key in doggy) {
  console.log(`${key}: ${doggy[key]}`);
}

break와 continue

반복문 안에서는 break와 continue를 통하여 반복문에서 벗어나거나, 그 다음 루프를 돌게끔 할수 있다

for (let i = 0; i < 10; i++) {
  if (i === 2) continue; // 다음 루프를 실행
  console.log(i);
  if (i === 5) break; // 반복문을 끝내기
}

i 가 2일땐 continue를 하여 원래 console.log를 해야 하지만 그 코드를 수행하지 않고 바로 3으로 넘어간다.

i가 5일땐 break를 하여 반복문을 종료 시킨다.

연습

numbers라는 배열을 파라미터로 받아서 총합을 구하는 함수를 만들어본다.

function sumOf(numbers) {
  let sum = 0;
  for (let i = 0; i < numbers.length; i++) {
    sum += numbers[i];
  }
  return sum;
}

const result = sumOf([1, 2, 3, 4, 5]);
console.log(result);

 

'공부내용정리 > JavaScript' 카테고리의 다른 글

프로토타입과 클래스  (0) 2021.04.18
배열 내장함수  (0) 2021.04.18
배열  (0) 2021.04.15
객체  (0) 2021.04.14
함수  (0) 2021.04.13

객체는 한 변수 혹은 상수에 여러가지 장보를 담기 위함이었다면, 배열은 여러개의 항목들이 들어있는 리스트와 같다.

숫자배열을 선언해 보자.

const array = [1, 2, 3, 4, 5];

배열을 선언 할때는 []안에 감싸주면 된다.

배열 안에는 어떤 값이던지 넣을 수 있다.

객체 배열을 만들어보자.

const objects = [{ name: '멍멍이' }, { name: '야옹이' }];

배열을 선언하고 나서, n번째 항목을 조회하고 싶을 땐 다음과 같이 할수 있다.

objects[n];

다음 코드를 입력해 보자.

const objects = [{ name: '멍멍이' }, { name: '야옹이' }];

console.log(objects);
console.log(objects[0]);
console.log(objects[1]);

주의점, 첫번째 항목이 objects[1]이 아니라 object[0]이라는 것이다. objects[1]이 두번째 항목이다.

배열에 새 항목 추가하기

배열에 새로운 항목을 추가 할때는 배열이 지니고 있는 내장함수인 push 함수를 사용한다.

다음 코드를 보자.

const objects = [{ name: '멍멍이' }, { name: '야옹이' }];

objects.push({
  name: '멍뭉이'
});

console.log(objects);

배열의 크기 알아내기

배열의 크기를 알아낼 떄에는 배열의 length값을 확인한다.

const objects = [{ name: '멍멍이' }, { name: '야옹이' }];

console.log(objects.length);

objects.push({
  name: '멍뭉이'
});

console.log(objects.length);

 

'공부내용정리 > JavaScript' 카테고리의 다른 글

배열 내장함수  (0) 2021.04.18
반복문  (0) 2021.04.15
객체  (0) 2021.04.14
함수  (0) 2021.04.13
조건문  (0) 2021.04.12

객체는 변수 혹은 상수를 사용하게 될 때 하나의 이름에 여러 종류의 값을 넣을 수 있게 해준다.

const dog = {
  name: '멍멍이',
  age: 2
};

console.log(dog.name);
console.log(dog.age);

결과

멍멍이
2

객체를 선언할떄는 {}문자 안에 원하는 값들을 넣어준다. 값을 집어 넣을때는

키: 원하는 값

형태로 넣고, 키에 해당하는 부분은 공백이 ㅇ벗어야 된다. 만약에 공백이 있어야 하는 상황이라면 따옴표로 감싸서 문자열로 넣어주면 된다.

const sample = {
  'key with space': true
};

어벤져스의 캐릭터 아이언맨과 캡틴 아메리카 정보를 객체안에 넣어보자.

const ironMan = {
  name: '토니 스타크',
  actor: '로버트 다우니 주니어',
  alias: '아이언맨'
};

const captainAmerica = {
  name: '스티븐 로저스',
  actor: '크리스 에반스',
  alias: '캡틴 아메리카'
};

console.log(ironMan);
console.log(captainAmerica);

결과이다.

함수에서 객체를 파라미터로 받기

함수를 새로 만들어서 방금 만든 객체를 파라미터로 받아와서 사용해보자.

const ironMan = {
  name: '토니 스타크',
  actor: '로버트 다우니 주니어',
  alias: '아이언맨'
};

const captainAmerica = {
  name: '스티븐 로저스',
  actor: '크리스 에반스',
  alias: '캡틴 아메리카'
};

function print(hero) {
  const text = `${hero.alias}(${hero.name}) 역할을 맡은 배우는 ${
    hero.actor
  } 입니다.`;
  console.log(text);
}

print(ironMan);
print(captainAmerica);

결과

아이언맨(토니 스타크) 역할을 맡은 배우는 로버트 다우니 주니어 입니다.
캡틴 아메리카(스티븐 로저스) 역할을 맡은 배우는 크리스 에반스 입니다.

객체 비구조화 할당

print 함수를 보면 파라미터로 받아온 hero 내부의 값을 조회 할때 마다 hero.을 입력하고 있는데, 객체 비구조화 할당이라는 문법을 사용하면 코드를 더욱 짧고 보기 좋게 작성 할 수 있다.

이 문법은 "객체 구조 분해" 라고 불리기도 한다.

const ironMan = {
  name: '토니 스타크',
  actor: '로버트 다우니 주니어',
  alias: '아이언맨'
};

const captainAmerica = {
  name: '스티븐 로저스',
  actor: '크리스 에반스',
  alias: '캡틴 아메리카'
};

function print(hero) {
  const { alias, name, actor } = hero;
  const text = `${alias}(${name}) 역할을 맡은 배우는 ${actor} 입니다.`;
  console.log(text);
}

print(ironMan);
print(captainAmerica);
const { alias, name, actor } = hero;

이코드가 객체에서 값들을 추출해서 새로운 상수로 선언해 주는것이다.

여기서 더 나아가면, 파라미터 단계에서 객체 비구조화 할당을 할수도 있다.

const ironMan = {
  name: '토니 스타크',
  actor: '로버트 다우니 주니어',
  alias: '아이언맨'
};

const captainAmerica = {
  name: '스티븐 로저스',
  actor: '크리스 에반스',
  alias: '캡틴 아메리카'
};

function print({ alias, name, actor }) {
  const text = `${alias}(${name}) 역할을 맡은 배우는 ${actor} 입니다.`;
  console.log(text);
}

print(ironMan);
print(captainAmerica);

객체 안에 함수 넣기

객체안에 함수를 넣을때도 있다.

const dog = {
  name: '멍멍이',
  sound: '멍멍!',
  say: function say() {
    console.log(this.sound);
  }
};

dog.say();

결과

멍멍!

함수가 객체안에 들어가게되면, this는 자신이 속해있는 객체를 가르키게 된다.

함수를 선언할때는 이름이 없어도 된다.

const dog = {
  name: '멍멍이',
  sound: '멍멍!',
  say: function() {
    console.log(this.sound);
  }
};

dog.say();

이전과 똑같이 동작할것이다.

객체안에 함수를 넣을때, 화살표 함수로 선언한다면 제대로 작동하지 않는다.

이유는 function으로 선언한 함수는 this가 제대로 자신이 속한 객체를 가르키게 되는데, 화살표 함수는 그렇지 않기 때문이다.

Getter함수와 Setter함수

객체 안에 Getter함수와 Setter함수를 설정하는 방법을 알아봅시다. 객체를 만들고 나면, 다음과 같이 객체안의 값을 수정할 수도 있다.

const numbers = {
  a: 1,
  b: 2
};

numbers.a = 5;
console.log(numbers);

Getter함수와 Setter함수를 사용하게 되면 특정 값을 바꾸려고 하거나, 특정 값을 조회하려고 할 때 우리가 원하는 코드를 실행 시킬수 있다.

const numbers = {
  a: 1,
  b: 2,
  get sum() {
    console.log('sum 함수가 실행됩니다!');
    return this.a + this.b;
  }
};

console.log(numbers.sum);
numbers.b = 5;
console.log(numbers.sum);

numbers.sum()을 한 것이 아니라 number.sum을 조회 했을 뿐인데, 함수가 실행 되고 그 결과 값이 출력되었습니다.

이런식으로 Getter함수는 특정 값을 조회 할 때 우리가 설정한 함수로 연산된 값을 반환한다.

이번에는 Setter함수를 사용해보자.

const numbers = {
  _a: 1,
  _b: 2,
  sum: 3,
  calculate() {
    console.log('calculate');
    this.sum = this._a + this._b;
  },
  get a() {
    return this._a;
  },
  get b() {
    return this._b;
  },
  set a(value) {
    console.log('a가 바뀝니다.');
    this._a = value;
    this.calculate();
  },
  set b(value) {
    console.log('b가 바뀝니다.');
    this._b = value;
    this.calculate();
  }
};

console.log(numbers.sum);
numbers.a = 5;
numbers.b = 7;
numbers.a = 9;
console.log(numbers.sum);
console.log(numbers.sum);
console.log(numbers.sum);

Setter함수를 설정 할때는 함수의 앞부분에 set키워드를 붙인다.

Setter함수를 설정하고 나면, numbers.a = 5이렇게 값을 설정했을때 5를 함수의 파라미터로 받아오게 된다. 위 코드에서는 객체 안에 _a, _b 라는 숫자를 선언해주고, 이 값들을 위한 Getter와 Setter함수를 설정해 주었다

아까는 만든객체에서는 numbers.sum이 조회 될 때 마다 덧셈이 이루어졌었지만, 이제는 a 혹은 b값이 바뀔때 마다 sum값을 연산한다.

'공부내용정리 > JavaScript' 카테고리의 다른 글

반복문  (0) 2021.04.15
배열  (0) 2021.04.15
함수  (0) 2021.04.13
조건문  (0) 2021.04.12
연산자  (0) 2021.04.10

함수는 특정 코드를 하나의 명령으로 실행 할수 있게 해주는 기능이다.

예를 들어서, 특정 값들의 합을 구하고 싶을떄는 다음과 같은 코드를 작성한다.

const a = 1;
const b = 2;
const sum = a + b;

이 작업을 함수로 만들어 보겠다.

function add(a, b) {
  return a + b;
}

const sum = add(1, 2);
console.log(sum);

결과는 3이 된다.

 

함수를 만들 때는 function 키워드를 사용하며, 함수에서 어떤 값을 받아올지 정해주는데 이를 파라미터(매개변수)라고 부른다.

 

함수내부에서 return 키워드를 사용하여 함수의 결과물을 지정 할수 있다.

추가적으로, return을 하게 되면 함수가 끝난다. 만약 다음과 같이 코드가 작성된다면, return 아래의 코드는 호출이 안된다.

 

추가적으로 return을 하게 되면 함수가 끝난다. 만약 다음과 같이 코드가 작성되있다면, return 아래의 코드는 호출이 안된다.

function add(a, b) {
  return a + b;
  console.log('호출이 되지 않는 코드!');
}

const sum = add(1, 2);
console.log(sum);

연습

함수를 연습해 보자.

Hello, name!

name이라는 파라미터를 넣으면 콘솔에 'Hello name!'이라는 결과를 출력하는 코드를 작성해보자.

function hello(name) {
  console.log('Hello, ' + name + '!');
}
hello('mang');

결과는 다음과 같다.

"Hello, mang!"

console.log를 하게 될때 우리는 문자열을 조합하기 위해서 + 연산자를 사용했다. 이렇게 문자열을 조합 할 때 + 를 사용해도 큰 문제는 없지만, 더욱 편하게 조합을 하는 방법이 있습니다. 바로 ES6의 템플릿 리터럴이라는 문법을 사용하는 것이다.

 

es6란?

ES6 는 ECMAScript6 를 의미하며, 자바스크립트의 버전을 가르킵니다. ES6는 2015년에 도입이 되었습니다. ES6 는 ES2015 라고 불리기도 합니다. 그리고 2015년 이후에 계속해서 새로운 자바스크립트 버전이 나오고 있습니다. ES7(ES2016) ES8(ES2017) ES9(ES2018) ES10(ES2019).. 새로운 자바스크립트 버전이 나올때마다 새로운 문법이 소개됩니다.

브라우저 버전에 따라 지원되는 자바스크립트 버전이 다릅니다. 하지만, 보통 웹 개발을 할 때에는 Babel 이라는 도구를 사용하여 최신 버전의 자바스크립트가 구버전의 브라우저에서도 실행되도록 할 수 있습니다. (정확히는, 최신버전 자바스크립트를 구버전 형태로 변환하는 작업을 거칩니다.)

 

템플릿 리터럴을 사용하여 구현을 해보자.

function hello(name) {
  console.log(`Hello, ${name}!`);
}
hello('mang');

 

점수를 성적등급으로 변환하기

이번에는 점수가 주어졌을 때, A, B, C, D, F 등급을 반환하는 함수를 만들어 보자

function getGrade(score) {
  if (score === 100) {
    return 'A+';
  } else if (score >= 90) {
    return 'A';
  } else if (score === 89) {
    return 'B+';
  } else if (score >= 80) {
    return 'B';
  } else if (score === 79) {
    return 'C+';
  } else if (score >= 70) {
    return 'C';
  } else if (score === 69) {
    return 'D+';
  } else if (score >= 60) {
    return 'D';
  } else {
    return 'F';
  }
}

const grade = getGrade(90);
console.log(grade);

grade가 90일때는 결과가 A가 된다.

 

화살표 함수

함수를 선언하는 방식중 또 다른 방법은 화살표 함수 문법을 사용 하는 것이다.

const add = (a, b) => {
  return a + b;
};

console.log(add(1, 2));

function키워드 대신에 =>문자를 사용해서 함수를 구현했는데, 화살표 좌측에는 함수의 파라미터, 화살표의 우측에는 코드 블록이 들어온다.

그런데, 만약 위와 같이 코드 블록 내부에서 바로 return을 하는 경우는 다음과 같이 줄여서 쓸 수도 있다.

const add = (a, b) => a + b;
console.log(add(1, 2));

아까는 만들었던 getGrade함수처럼 여러줄로 구성되어 있는 경우에는 코드 블록을 만들어야 한다.

const getGrade = score => {
  if (score === 100) {
    return 'A+';
  } else if (score >= 90) {
    return 'A';
  } else if (score === 89) {
    return 'B+';
  } else if (score >= 80) {
    return 'B';
  } else if (score === 79) {
    return 'C+';
  } else if (score >= 70) {
    return 'C';
  } else if (score === 69) {
    return 'D+';
  } else if (score >= 60) {
    return 'D';
  } else {
    return 'F';
  }
};
const grade = getGrade(90);
console.log(grade);

 

'공부내용정리 > JavaScript' 카테고리의 다른 글

배열  (0) 2021.04.15
객체  (0) 2021.04.14
조건문  (0) 2021.04.12
연산자  (0) 2021.04.10
변수와 상수  (0) 2021.04.10

+ Recent posts