결과 화면

Plus 버튼을 누르면 숫자가 1 증가하고, Minus 버튼을 누르면 숫자가 1 감소한다.


1. 바닐라 자바스크립트로 카운터 만들기

  • index.html
<body>
    <button id="minus">Minus</button>
    <span id="number"></span>
    <button id="plus">Plus</button>
</body>

 

  • index.js
// html 태그 선택
const plus = document.getElementById('plus')
const minus = document.getElementById('minus')
const number = document.getElementById('number')

// 초기값
let count = 0

// html 화면에 초기값 count 보여주기
number.innerText = count

// count가 변할 때 마다 화면에 보여주기
const updateText = () => {
  number.innerText = count
}

// count +1
const handlePlus = () => {
  count++
  updateText()
}

// count -1
const handleMinus = () => {
  count--
  updateText()
}

// 버튼 클릭 이벤트
plus.addEventListener('click', handlePlus)
minus.addEventListener('click', handleMinus)

 


※ 리덕스 기본 개념

  • store

data를 저장하는 곳이다.

import { createStore } from 'redux'
const store = createStore(reducer)

 

  • state(상태)

변경이 필요한 data이다.

 

  • reducre

state를 변경하는 function(함수)이다.

reducer의 return 값이 state가 된다.

const reducer = (state, action) => {}

 

  • action

reducer의 두번째 파라미터 값이다.

action을 통해서만 state를 변경할 수 있다.

action은 object(객체)타입만 가능하고, 그 key 값은 type만 가능하다. (action.type)

공식문서에 따르면 if문 보다는 switch문이랑 더 자주 사용된다.

 

  • dispatch

reducer에 action을 보내는 방법이다.

dispatch를 통해서만 action을 실행시킬 수 있다.

현재 이벤트를 발생시키는 함수라고 볼 수 있다.

store.dispatch({type: 액션이름})

 

  • subscribe

store 안에 있는 변화를 감지한다.

store.subscribe(함수호출)

 


2. 리덕스로 카운터 만들기

yarn add redux 또는 npm install redux

 

  • index.html
<body>
    <button id="plus">Plus</button>
    <span id="number"></span>
    <button id="minus">Minus</button>
</body>

 

  • index.js
import { createStore } from 'redux'

// html 태그 선택
const plus = document.getElementById('plus')
const minus = document.getElementById('minus')
const number = document.getElementById('number')

// 초기값
number.innerText = 0

// string을 직접 사용하기 보다는 변수로 만들어서 사용하는 것이 오타 등의 에러를 발견할 수 있어 효율적이다.
const ADD = 'ADD'
const MINUS = 'MINUS'

// 2. reducer(변수 이름은 자유)를 만든다.
const reduceCountModifier = (count = 0, action) => {
  // 3. action을 만든다.
  switch (action.type) {
    case ADD:
      return count + 1
    case MINUS:
      return count -1
    default:
      return count
  }
}

// 1. store를 만든다.
const countStore = createStore(reduceCountModifier)

// store 안에 있는 state를 가지고 온다.
const onChange = () => {
  number.innerText = countStore.getState()
}

// store 안에 있는 state의 변화를 감지한다.
countStore.subscribe(onChange)

// 4. dispatch를 만든다.
const handlePlus = () => {
  countStore.dispatch({type: ADD})
}
const handleMinus = () => {
  countStore.dispatch({type: MINUS})
}

// 클릭 이벤트
plus.addEventListener('click', handlePlus)
minus.addEventListener('click', handleMinus)

리덕스는 자바스크립트 앱을 위한 예측 가능한 상태(state) 컨테이너이다.

리덕스는 자바스크립트를 사용할 수 있다면 바닐라 자바스크립트, 리액트, 뷰, 앵귤러 등 여러 환경에서 함께 사용할 수 있다.

(리액트와 많이 사용하긴 하지만, 리액트를 위한 전용 라이브러리가 아니다.)

 

1. 깃허브 레포지토리 만들기

https://github.com/heejae0811/vanilla-redux

 

2. npx create-react-app vanilla-redux(레포이름)

 

3. 불필요한 파일 삭제하기

https://school.programmers.co.kr/learn/courses/30/lessons/12948

 

문제 설명

프로그래머스 모바일은 개인정보 보호를 위해 고지서를 보낼 때 고객들의 전화번호의 일부를 가립니다.
전화번호가 문자열 phone_number로 주어졌을 때, 전화번호의 뒷 4자리를 제외한 나머지 숫자를 전부 *으로 가린 문자열을 리턴하는 함수, solution을 완성해주세요.

 

제한조건

  • phone_number는 길이 4 이상, 20이하인 문자열입니다.

 

function solution(phone_number) {
    let length = phone_number.length - 4
    
    return phone_number.slice(0, length).replace(/[0-9]/g, "*") + phone_number.slice(length, phone_number.length)
}

https://school.programmers.co.kr/learn/courses/30/lessons/161990

 

문제 설명

코딩테스트를 준비하는 머쓱이는 프로그래머스에서 문제를 풀고 나중에 다시 코드를 보면서 공부하려고 작성한 코드를 컴퓨터 바탕화면에 아무 위치에나 저장해 둡니다. 저장한 코드가 많아지면서 머쓱이는 본인의 컴퓨터 바탕화면이 너무 지저분하다고 생각했습니다. 프로그래머스에서 작성했던 코드는 그 문제에 가서 다시 볼 수 있기 때문에 저장해 둔 파일들을 전부 삭제하기로 했습니다.

컴퓨터 바탕화면은 각 칸이 정사각형인 격자판입니다. 이때 컴퓨터 바탕화면의 상태를 나타낸 문자열 배열 wallpaper가 주어집니다. 파일들은 바탕화면의 격자칸에 위치하고 바탕화면의 격자점들은 바탕화면의 가장 왼쪽 위를 (0, 0)으로 시작해 (세로 좌표, 가로 좌표)로 표현합니다. 빈칸은 ".", 파일이 있는 칸은 "#"의 값을 가집니다. 드래그를 하면 파일들을 선택할 수 있고, 선택된 파일들을 삭제할 수 있습니다. 머쓱이는 최소한의 이동거리를 갖는 한 번의 드래그로 모든 파일을 선택해서 한 번에 지우려고 하며 드래그로 파일들을 선택하는 방법은 다음과 같습니다.

 

  • 드래그는 바탕화면의 격자점 S(lux, luy)를 마우스 왼쪽 버튼으로 클릭한 상태로 격자점 E(rdx, rdy)로 이동한 뒤 마우스 왼쪽 버튼을 떼는 행동입니다. 이때, "점 S에서 점 E로 드래그한다"고 표현하고 점 S와 점 E를 각각 드래그의 시작점, 끝점이라고 표현합니다.
  • 점 S(lux, luy)에서 점 E(rdx, rdy)로 드래그를 할 때, "드래그 한 거리"는 |rdx - lux| + |rdy - luy|로 정의합니다.
  • 점 S에서 점 E로 드래그를 하면 바탕화면에서 두 격자점을 각각 왼쪽 위, 오른쪽 아래로 하는 직사각형 내부에 있는 모든 파일이 선택됩니다.

 

예를 들어 wallpaper = [".#...", "..#..", "...#."]인 바탕화면을 그림으로 나타내면 다음과 같습니다. 이러한 바탕화면에서 다음 그림과 같이 S(0, 1)에서 E(3, 4)로 드래그하면 세 개의 파일이 모두 선택되므로 드래그 한 거리 (3 - 0) + (4 - 1) = 6을 최솟값으로 모든 파일을 선택 가능합니다.

 

(0, 0)에서 (3, 5)로 드래그해도 모든 파일을 선택할 수 있지만 이때 드래그 한 거리는 (3 - 0) + (5 - 0) = 8이고 이전의 방법보다 거리가 늘어납니다.

머쓱이의 컴퓨터 바탕화면의 상태를 나타내는 문자열 배열 wallpaper가 매개변수로 주어질 때 바탕화면의 파일들을 한 번에 삭제하기 위해 최소한의 이동거리를 갖는 드래그의 시작점과 끝점을 담은 정수 배열을 return하는 solution 함수를 작성해 주세요. 드래그의 시작점이 (lux, luy), 끝점이 (rdx, rdy)라면 정수 배열 [lux, luy, rdx, rdy]를 return하면 됩니다.

 

제한사항

  • 1 ≤ wallpaper의 길이 ≤ 50
  • 1 ≤ wallpaper[i]의 길이 ≤ 50
  • wallpaper의 모든 원소의 길이는 동일합니다.
  • wallpaper[i][j]는 바탕화면에서 i + 1행 j + 1열에 해당하는 칸의 상태를 나타냅니다.
  • wallpaper[i][j]는 "#" 또는 "."의 값만 가집니다.
  • 바탕화면에는 적어도 하나의 파일이 있습니다.
  • 드래그 시작점 (lux, luy)와 끝점 (rdx, rdy)는 lux < rdx, luy < rdy를 만족해야 합니다.

 

모든 좌표값을 모아서 최소, 최대값을 구한다.

function solution(wallpaper) {
    let array = []
    let startX = []
    let startY = []
    
    wallpaper.map((rows, idx) => {
        [...rows].map((cols, key) => {
            if(cols === '#') {
                startX.push(idx)
                startY.push(key)
            }
        })
    })
    
    return [Math.min(...startX), Math.min(...startY), Math.max(...startX) + 1, Math.max(...startY) + 1]
}

https://school.programmers.co.kr/learn/courses/30/lessons/12919

 

문제 설명

String형 배열 seoul의 element중 "Kim"의 위치 x를 찾아, "김서방은 x에 있다"는 String을 반환하는 함수, solution을 완성하세요. seoul에 "Kim"은 오직 한 번만 나타나며 잘못된 값이 입력되는 경우는 없습니다.

 

제한사항

  • seoul은 길이 1 이상, 1000 이하인 배열입니다.
  • seoul의 원소는 길이 1 이상, 20 이하인 문자열입니다.
  • "Kim"은 반드시 seoul 안에 포함되어 있습니다.

 

indexOf(): 호출한 string 객체에서 주어진 값과 일치하는 첫 번째 인덱스를 반환한다. 일치하는 값이 없으면 -1을 반환한다.

function solution(seoul) {
    return '김서방은 ' + seoul.indexOf('Kim') + '에 있다'
}

sort() 메서드는 배열의 요소를 적절한 위치에 정렬한 후 그 배열을 반환한다. 기본 정렬 순서는 문자열의 유니코드 코드 포인트를 따른다.

 

  • sort()

sort()만 사용할 경우 유니코드 순서에 따라서 오름차순으로 정렬되기 때문에 아래와 같은 결과가 출력된다.

const str = ['dog', 'Cat', 'apple', 'car', 'Banana', 'eye']
const num = [10, 7, 1280, 720, 456, 123]

str.sort() // [ 'Banana', 'Cat', 'apple', 'car', 'dog', 'eye' ]
num.sort() // [ 10, 123, 1280, 456, 7, 720 ]

 

  • sort() 숫자 오름차순
const num = [10, 7, 1280, 720, 456, 123]

num.sort((a, b) => a - b) // [ 7, 10, 123, 456, 720, 1280 ]

 

  • sort() 숫자 내림차순
const num = [10, 7, 1280, 720, 456, 123]

num.sort((a, b) => b - a) // [ 1280, 720, 456, 123, 10, 7 ]

 

  • sort() 문자열 오름차순

영어 대문자, 소문자가 섞여있을 경우, 대문자가 소문자보다 앞에 오도록 정렬된다.

숫자 > 영어 대문자 > 영어 소문자 > 한글

const str1 = ['dog', 'Cat', 'apple', 'car', 'Banana', 'eye']
const str2 = ['강아지', '고양이', '사과', '자동차', '바나나', '눈']
const str3 = ['dog', '고양이', '사과', '자동차', 'Banana', '눈', '100종원']

str1.sort((a, b) => a > b ? 1 : -1) // [ 'Banana', 'Cat', 'apple', 'car', 'dog', 'eye' ]
str2.sort((a, b) => a > b ? 1 : -1) // [ '강아지', '고양이', '눈', '바나나', '사과', '자동차' ]
str3.sort((a, b) => a > b ? 1 : -1) // ['100종원', 'Banana', 'dog', '고양이', '눈', '사과', '자동차']

 

  • sort() 문자열 내림차순

영어 대문자, 소문자가 섞여있을 경우, 대문자가 소문자보다 뒤에 오도록 정렬된다.

한글 > 영어 소문자 > 영어 대문자 > 숫자

const str1 = ['dog', 'Cat', 'apple', 'car', 'Banana', 'eye']
const str2 = ['강아지', '고양이', '사과', '자동차', '바나나', '눈']
const str3 = ['dog', '고양이', '사과', '자동차', 'Banana', '눈', '100종원']

str1.sort((a, b) => a > b ? -1 : 1) // [ 'eye', 'dog', 'car', 'apple', 'Cat', 'Banana' ]
str2.sort((a, b) => a > b ? -1 : 1) // [ '자동차', '사과', '바나나', '눈', '고양이', '강아지' ]
str3.sort((a, b) => a > b ? -1 : 1) // ['자동차', '사과', '눈', '고양이', 'dog', 'Banana', '100종원']

 

  • sort() 대소문자 구분없이 오름차순

대소문자 구분 없이 정렬해주는 함수는 없기 때문에 toLowerCawe() 또는 toUpperCase() 메서드를 사용해서 소문자 또는 대문자로 변경한 후 비교해 정렬한다.

const str = ['dog', 'Cat', 'apple', 'car', 'Banana', 'eye']

str1.sort((a, b) => {
    const upperCaseA = a.toUpperCase()
    const upperCaseB = b.toUpperCase()

    if(upperCaseA > upperCaseB) return 1
    if(upperCaseA < upperCaseB) return -1
    if(upperCaseA === upperCaseB) return 0
})

// [ 'apple', 'Banana', 'car', 'Cat', 'dog', 'eye' ]

 

  • sort() 대소문자 구분없이 내림차순
const str = ['dog', 'Cat', 'apple', 'car', 'Banana', 'eye']

str.sort((a, b) => {
    const upperCaseA = a.toUpperCase()
    const upperCaseB = b.toUpperCase()

    if(upperCaseA > upperCaseB) return -1
    if(upperCaseA < upperCaseB) return 1
    if(upperCaseA === upperCaseB) return 0
})

// [ 'eye', 'dog', 'Cat', 'car', 'Banana', 'apple' ]

https://school.programmers.co.kr/learn/courses/30/lessons/12933

 

문제 설명

함수 solution은 정수 n을 매개변수로 입력받습니다. n의 각 자릿수를 큰것부터 작은 순으로 정렬한 새로운 정수를 리턴해주세요. 예를들어 n이 118372면 873211을 리턴하면 됩니다.

 

제한조건

  • n은 1이상 8000000000 이하인 자연수입니다.

 

function solution(n) {
    return Number([...String(n)].sort((a, b) => b - a).join(''))
}

https://school.programmers.co.kr/learn/courses/30/lessons/12916

 

문제 설명

대문자와 소문자가 섞여있는 문자열 s가 주어집니다. s에 'p'의 개수와 'y'의 개수를 비교해 같으면 True, 다르면 False를 return 하는 solution를 완성하세요. 'p', 'y' 모두 하나도 없는 경우는 항상 True를 리턴합니다. 단, 개수를 비교할 때 대문자와 소문자는 구별하지 않습니다.
예를 들어 s가 "pPoooyY"면 true를 return하고 "Pyy"라면 false를 return합니다.

 

제한사항

  • 문자열 s의 길이 : 50 이하의 자연수
  • 문자열 s는 알파벳으로만 이루어져 있습니다.

 

function solution(s){
    const arr = [...s.toLowerCase()]
    const p = arr.filter(list => list === 'p')
    const y = arr.filter(list => list === 'y')
    
    return p.length === y.length ? true : false
}

문자열(String)을 배열로 만들기

  • 전개 연산자(Spread Operator)

전개 연산자를 사용하면 배열이나 문자열 같이 반복 가능한 0개 이상의 인수 또는 요소로 확장하여, 0개 이상의 키-값 쌍으로 객체를 확장시킬 수 있다.

const str = 'abc'
const arrStr = [...str]

arrStr // ['a', 'b', 'c']

 

  • split()

split() 메서드는 string 객체를 지정한 구분자를 이용하여 여러 개의 문자열로 나눈다.

const str = 'abc'
const arrStr = str.split('')

arrStr //  ['a', 'b', 'c']

 

  • Array.from()

Array.from() 메서드는 유사 배열 객체나 반복 가능한 객체를 얕게 복사해 새로운 배열을 만든다.

Array.from('abc') // ['a', 'b', 'c']

 

숫자(Number)을 배열로 만들기

map, split 등의 메소드들이 문자열에서만 사용이 가능하기 때문에 타입을 문자열로 바꾼 후, 다시 숫자로 바꿔준다.

 

  • String() + Number() + map()

String() 함수를 사용하여 다른 타입의 값을 문자열로 바꿀 수 있다.

Number() 함수를 사용하여 다른 타입의 값을 숫자로 바꿀 수 있다.

map() 메서드는 배열 내의 모든 요소에 대하여 주어진 함수를 호출한 결과를 모아 새로운 배열로 반환한다.

const num = 123
const arrNum = [...String(num)].map(Number)

arrNum // [1, 2, 3]

 

  • toString() + map()

toString() 메서드는 문자열을 반환한다.

const num = 123
const arrNum = num.toString().split('').map(Number)

arrNum // [1, 2, 3]

 

  • 문자열 더하기 + Array.from()

숫자에 문자를 더하면 타입이 문자열로 바뀐다.

const num = 123
const arrNum = (num + '').split('')

Array.from(arrNum, Number) // [1, 2, 3]

https://school.programmers.co.kr/learn/courses/30/lessons/12944

 

문제 설명

정수를 담고 있는 배열 arr의 평균값을 return하는 함수, solution을 완성해보세요.

 

제한사항

  • arr은 길이 1 이상, 100 이하인 배열입니다.
  • arr의 원소는 -10,000 이상 10,000 이하인 정수입니다.

 

function solution(arr) {
    return arr.reduce((arr, cur) => arr + cur) / arr.length
}

+ Recent posts