9일차

개발 log·2021년 7월 20일
0

TIL

목록 보기
6/21

배열 내장함수


forEach

가장 쉬운 배열 내장함수
forEach 함수의 파라미터로는, 각 원소에 대하여 처리하고 싶은 코드를 함수로 넣어줌
이렇게 함수형태의 파라미터를 전달하는 것을 콜백함수 라고 함

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

superheroes.forEach(hero => {
    console.log(hero); // 아이언맨  캡틴 아메리카  토르  닥터 스트레인지
})

map

map은 배열 안의 각 원소를 변환할 때 사용 되며
이 과정에서 새로운 배열이 만들어짐
map 함수의 파라미터로는 변화를 주는 함수를 전달해줌(변화함수)

파라미터로 변화함수를 주어 해당 함수조건에 맞는 새로운 배열을 생성해줌

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

예제

배열 안의 모든 숫자를 제곱해서 새로운 배열을 만들어 보자

예시 1 (내장함수X)

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

예시 2 (forEach 사용)

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

const squared = [];

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

console.log(squared);

예시 3 (map 사용)

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

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

indexOf

indexOf는 원하는 항목이 몇번째 원소인지 찾아주는 함수
파라미터로 원하는 값을 넣어줌

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

findIndex

만약 배열 안에 있는 값이 객체이거나 배열이라면 indexOf로 찾을 수 없고
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함수는 배열에서 특정 조건을 만족하는 값들만 따로 추출하여 새로운 배열을 만듬
filter함수의 파라미터로는 조건을 검사하는 함수를 넣어주며
이 함수의 파라미터로 각 원소의 값을 받아오게 됨

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

예를 들어 이전에 만든 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}]

splice

splice는 배열에서 특정 항목을 제거할 때 사용함
첫번째 파라미터는 어떤 인덱스부터 지울지를 의미하고 (시작점)
두번째 파라미터는 그 인덱스로부터 몇개를 지울지를 의미 (갯수)

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

slice

주로 배열을 잘라낼 때 사용하며 splice와 비슷하지만
중요한 점은 기존의 배열은 건들이지 않음
slice에는 두개의 파라미터를 넣게 되는데
첫번째 파라미터는 어디서부터 자를지 (시작점)
두번째 파라미터는 어디까지 자를지를 의미 (끝점)

const numbers = [10, 20, 30, 40];
const sliced = numbers.slice(0, 2); // 0부터 시작해서 2전까지

console.log(sliced); // [10, 20]
console.log(numbers); // [10, 20, 30, 40]

shift와 pop

shiftpop은 비슷하지만 다름
shift는 첫번째 원소를 배열에서 추출함 (추출하며 배열에서 해당 원소는 소멸)

shift

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

pop

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

unshift와 push

shiftpop이 배열에서 값을 추출했다면
unshiftpush는 배열에 값을 추가하는 것

unshift

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

push

const numbers = [10, 20, 30, 40];
numbers.push(50);
console.log(numbers); // [10, 20, 30, 40, 50]

concat

concat은 여러개의 배열을 하나의 배열로 합쳐줌
concat함수는 arr1과 arr2에 변화를 주지 않음

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

console.log(concated); // [1, 2, 3, 4, 5, 6]

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함수는 잘 사용할 줄 알면 유용한 내장함수


reduce 예제

  • 주어진 배열의 총합을 구해야하는 상황

forEach로 구현

sum을 계산하기 위해 사전에 sum을 선언하고 forEach를 통해 덧셈을 누적시킴

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

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

reduce로 구현

reduce함수에는 두개의 파라미터를 전달함
첫번째 파라미터는 accumulatorcurrent를 파라미터로 가져와서 결과를 반환하는 콜백함수
두번째 파라미터는 reduce함수에서 사용할 초깃값
accumulator는 누적된 값을 의미

쉽게 생각하면 reduce함수로 반환한 값이 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);

평균 구하기

추가적으로 indexarray 파라미터도 받아옴
index는 현재 처리하고 있는 항목이 몇 번째인지 가르키고
array는 현재 처리하고 있는 배열 자신을 의미

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

다른 예시

숫자가 아니더라도 가능함
각 원소가 몇 개씩 있는지 세어보는 함수 제작
초기값을 {}객체로 설정

const alphabets = ['a', 'a', 'a', 'b', 'c', 'c', 'd', 'e']
const count = alphabets.reduce((acc, current) => {
    if (acc[current]) {
        acc[current] += 1
    } else {
        acc[current] = 1
    }
    return acc
}, {})

console.log(count); // {a: 3, b: 1, c: 2, d: 1, e: 1}

프로토타입과 클래스


객체 생성자

객체 생성자를 네이밍 할때는 반드시 첫글자 대문자
새로운 객체를 만들때는 new 키워드 필요

function 이름(파라미터) {
    this.변수명 = 파라미터;
    this.함수명 = function() {
        console.log(this.변수명)
    }
}
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(); // 야옹

프로토타입

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

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); // 1
console.log(cat.sharedValue); // 1

객체 생성자 상속받기

아래 코드를 보면 두개의 클래스는 거의 똑같은데 미묘한 차이로 두번이나 선언함 <- 비효율적
이럴 때 사용하는 것이 상속


function Dog(name, sound) {
    this.type = '개';
    this.name = name;
    this.sound = sound;
}
function Cat(name, sound) {
    this.type = '고양이';
    this.name = name;
    this.sound = sound;
}

Dog.prototype.say = function() {
    console.log(this.sound);
}
Cat.prototype.say = function() {
    console.log(this.sound);
}

클래스.call(this, ...)의 형태로 사용하고
상속받는 클래스.prototype = 부모 클래스.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;

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

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

// 프로토타입 공유
Dog.prototype = Animal.prototype;
Cat.prototype = Animal.prototype;

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

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

클래스

ES6 이후부터는 class 문법이 JS에 추가됨
클래스 내부에 함수를 만들게 되면 자동으로 프로토타입으로 등록이 됨
확인법 console.log(클래스명.prototype.함수명)

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('고양이', '야옹이', '야옹');

상속

extends키워드를 통해 상속받음
super키워드를 통해 자신이 상속받은 클래스의 constructor(생성자)를 호출해줌

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('야옹이', '야옹');
const cat2 = new Cat('야오오옹옹이', '야오옹옹');

CSS 방법론 (BEM)

CSS 클래스네임을 더 효율적으로 짓기 위한 방법


BEM의 기본구조

BEM은 Block, Element, Modifier를 의미함
각각 __--로 구분함

.header__navigation--navi-text {
    color: red;
}

위 코드에서 headerBlock, navigationElement, navi-textModifier가 됨

BEM은 기본적으로 ID를 사용하지 않으며, calss만을 사용함
또한, 어떻게 보이는가가 아닌 어떤 목적인가에 다라 이름을 지음
예를 들어, 에러 메시지를 띄우는 <p>에게는 .red가 아닌 .error라는 이름을 줘야함
이름을 연결할 때는 block-name과 같이 하이픈 하나만 써서 연결


Block / Element / Modifier


Block

블럭이란 (독립적인 것이 핵심)
재사용 가능한 기능적으로 독립적인 페이지 컴포넌트
(A functionally independent page component that can be reused)
라고 불림
즉, 블럭 자체를 떼어다가 어딘가에서 쓸 수 있는 단위를 의미

Block


Element

엘리먼트란 블럭을 구성하는 단위 (의존적인 것이 핵심)
자신이 속한 블럭 내에서만 의미를 가지기 때문에 블럭 안에서 떼어다 다른 곳에 쓸 수 없음

Element


Element 예시 1

아래의 예시를 보면 .search-formBlock이고,
.search-form__input.search-form__buttonElement
search-form이란 블럭은 떼어내서 어디든 붙여도 됨
하지만 내부의 inputbutton은 검색을 위한 인풋창이고 버튼이기 때문에
search-form 안에서만 존재 의미가 있는 엘리먼트

<form class='search-form'>
    <input class='search-form__input'>
    <button class='search-form__button'>Search</button>
</form>

Element 예시 2

엘리먼트 또한 중첩 가능
.block > .block__element1 > .block__element2도 가능하다는 말
BEM의 재밌는 점은 .block__element2.block__element1의 하위 엘리먼트로 보지 않고
둘 모두 .block의 엘리먼트로 취급한다는 점
덕분에 클래스네임에 Cascading을 여러번 표시할 필요가 없음

Element 잘못된 예시

block__element의 형태를 띄고 있지 않음

<form class="search-form">
    <div class="search-form__content">
        <input class="search-form__content__input">
        <button class="search-form__content__button">Search</button>
    </div>
</form>
Element 올바른 예시
<form class="search-form">
    <div class="search-form__content">
        <input class="search-form__input"/>
        <button class="search-form__button">Search</button>
    </div>
</form>

Modifier

Modifier는 블럭이나 엘리먼트의 속성을 담당함
생긴게 조금 다르거나, 다르게 동작하는 블럭이나 엘리먼트를 만들 때 사용하면 됨

Modifier


Modifier 예시 1 - Boolean 타입

아래의 코드에서 --focused가 수식어에 해당함
이렇게 작성된 것을 Boolean타입이라고 하는데, 해당 값이 true라고 가정하고 사용함

<ul class="tab">
    <li class="tab__item tab__item--focused">탭 01</li>
    <li class="tab__item">탭 02</li>
    <li class="tab__item">탭 03</li>
</ul>

Modifier 예시 2 - Key-Value 타입

아래의 예시에서 cool-graytheme-normal, theme-specialKey-Value 타입

<div class="column">
  <strong class="title">일반 로그인</strong>
  <form class="form-login form-login--theme-normal">
    <input type="text" class="form-login__id"/>
    <input type="password" class="form-login__password"/>
  </form>
</div>
 
<div class="column">
  <strong class="title title--color-gray">VIP 로그인 (준비중)</strong>
  <form class="form-login form-login--theme-special form-login--disabled">
      <input type="text" class="form-login__id"/>
      <input type="password" class="form-login__password"/>
  </form>
</div>

이미지 출처 (https://nykim.work/15)

profile
개발자 지망생

0개의 댓글