전체 글 (165)

07
13

1. Math.sqrt를 사용하지 않은 수숫점 구하기.

  • 입력받은 수를 제곱근 값을 소숫점 두 자리까지만 리턴한다.
  • 셋째 자리에서 반올림한다.
function computeSquareRoot(num) {
  // 기준을 잡아줄 소숫점 자리들의 가장 작은 수를 배열에 만든다.
  const decimal = [1, 0.1, 0.01, 0.001];
  //기준이 될 result를 1로 둔다.
  let result = 1;
  // 반복문으로 기준이 된 result를 제곱해서 num보다 작은 경우
  for (let i = 0; i < decimal.length; i++) {
    while (result * result < num) {
  //result에 소숫점 자리를 더한다. num가 더해진 기준의 제곱보다 커질때 까지 반복.
      result = result + decimal[i];
    }
  // 만약 result의 제곱이 num와 같을때 바로 리턴.
    if (result * result === num) {
      return result;
  // 아니면 소숫점 빼주고
    } else {
      result = result - decimal[i];
    }
  }
  //소숫점 3번째에서 반올림
  return Number(result.toFixed(2));
}
  • 다른 방법으로는 '바빌로니아 법의 점화식'이 있다고 한다. 나는 이해할 수 없다...

2. 카이사르 암호

  • 문자열과 숫자를 입력받아 입력받은 숫자만큼 평행 이동시킨 문자열을 리턴한다.
  • 공백은 무시한다.

[시도 1]

function decryptCaesarCipher(str, secret) {
  // 일단 스트링을 다 split으로 다 땐다.
  let newStr = str.split('');
  // 때어낸 문자를 아스키코드로 변환하여 넣는다.
  let arr = []
  for(let i = 0; i < newStr.length; i++) {
    arr.push(newStr[i].charCodeAt())
  }
  // 지금 이 배열이 아스키 코드로 바꾼 스트링이 들어있는 배열
  let ascii = arr.map(arr => arr - secret)
  let result = '';
  // 배열들을 돌면서 빈칸을 빈칸을 걸러내고
  for(let i = 0; i < ascii.length; i++) {
    if(ascii[i] === 29) {
      result = result + ' '
    } else {
    //남은건 다시 문자로 바꿔서 반환
      result = result + String.fromCharCode(ascii[i])
    }
  }
  return String(arr);
}
  • 실패
  • 아스키코드의 표에서 보면 secret으로 큰 수를 받을 경우, 소문자를 넘어 대문자까지 넘어간다.
  • 소문자 만을 범위로 secret을 정해주어서 97번부터 122번 사이에서만 secret이 변환되도록 만들어야 한다.

[시도 2]

function decryptCaesarCipher(str, secret) {
  let strArr = [abcdefghijklmnopqrstuvwxyz]
  let newStr = str.split('')
  let indexArr = [];
  for(let i = 0; i < newStr.length; i++) {
    indexArr.push(strArr.indexOf(newStr[i]))
    }
  return indexArr
  }
  • 완전히 틀린 코드이다.
  • 아예 나올 수 있는 알파벳을 모두 넣어서 그 배열 속에서 반복문으로 index를 매칭 시키려고 했지만 실패
  • 다시 아스키코드의 범위를 지정하는 방법으로 돌아가기로 하였다.

[시도 3]

function decryptCaesarCipher(str, secret) {
    let newStr = '';
    // str을 split으로 다 자른다.
    let splitStr = str.split('')
    // 자른 newStr에 for...of로 모든 배열들을 다 찾아서
    for(let i of splitStr) {
      // 만약 빈칸이면
        if(i === ' ') {
          // 빈칸을 넣고
          newStr = newStr + ' '
          } else {
            // 만약 아스키 코드 표에서 소문자가 되는 97을 넘으면 맞으면, secret이동 후에 - 122(최대 숫자) 총 알파벳 갯수가 26개 니까 나머지에 122 더한다.
            // 97보다 작으면, secret이동 후에 - 122 그리고 26 나눠서 나머지에 마찬가지 122 더한다.
            newStr = newStr + String.fromCharCode((i.charCodeAt(0) > 97) 
            	? (i.charCodeAt(0) - secret - 122) % 26 + 122 
                : (i.charCodeAt(0) - secret - 122) % 26 + 122)
            };
    }
    return newStr;
}
  • 문제 해결!
  • 조건을 걸 때, 총 알파벳 개수(26)와 최소 97, 최대 122가 나온다는 것을 바탕으로 범위를 정했다.
  • for... of와 삼항 연산자로 코드를 조금 더 간결하게도 바꿨다.
COMMENT
 
07
12

1. 사건의 발단

  • state값으로 form을 만들어서 입력된 값을 다시 state로 올려 렌더링 하는 작업을 하려고 하였다.
  • 직접 state값을 수정해도 가능은 하지만 이는 지양해야 한다. useState를 이용하는 것이 옳다.
  • 그래서 수정한 뒤 결과를 보니 게속 테스트가 통과되지 않는 것이다!!
  • 정작 틀린 부분은 또 오타 때문이었다고 한다...

2. useState 만들기

  const [msg, setMsg] = useState('');
  const [name, setName] = useState('');
  const [newFrind, setNewFrid] = useState([...FrindList]);
  • 먼저, state를 정해주고 다른 파일의 FrindList를 가져왔다.
  • 위의 msg와 name의 입력은 input의 text이고 그 내용은 생략한다.

3. 받아올 객체 폼 만들기

const frind = {
      id: Math.floor(Math.random() * 100000), //거의 무작위에 가까운 id값을 줬다.
      frindName: name,
      content: msg,
    };
  • FrindList에 있는 id와 frindName, content를 이용해 똑같은 구조의 객체 폼을 만들었고, 입력된 내용을 받아 올 것이다.

4. useState로 state값을 변경해 준다.

const newFrindCopy = newFrind.slice(0);
    newFrindCopy.unshift(frind);
    setNewTweet(newFrindCopy);
  • 계속 이어서, 우리가 직접 props로 받은 값을 바꿔주지 않기 위해 복사본을 slice로 만들고, 그 복사본에 unshift를 해서 state를 변경해 준다!

5. 렌더링 하기

const newFrinds = newFrind.map(newFrind => <Frind frind={newFrind} id={newFrind.id} />
  • map을 사용해서 알맞은 컴포넌트에 우리가 얻어온 newFrind를 집어넣고, 어디든지 {newFrind}로 렌더링 할 수 있다.
이처럼 state값을 어느정도 자유롭게 사용할 수 있다고 생각한다. 복사본을 만들면 되니까 말이다. 물론 구조 분해 할당으로 간단하게 해결할 수 도 있지만 좀 더 직관적으로 이렇게 만들어 보았다. 다른 사람들은 조금 이상한 방법이라고 말하기도 했다. 결국 둘 다 잘 작동하니 상관은 없지만 사람들이 자주 사용하는 방법을 사용하는 것이 좋지 않을까?
COMMENT
 
07
11

1. 사건의 발단

  • useState를 올바르게 사용할 수 있게 되었더니 props로 정보를 더 다양하게 주고받으면 범용성이 많이 올라갈 것이라고 생각했다.
  • 지금도 props를 사용하고 있지만 원리를 정확히 알고 사용하는 것이 좋겠다.

2. 기본적인 사용법

  • 부모 컴포넌트에서 자식 컴포넌트로 데이터를 줄 때 사용한다.
  • <컴포넌트 이름 props의 이름 = "주고싶은 값" />의 형태로 사용할 수 있다.
import React from 'react';

function App() {
	return (
		<div>
			<Greet name="Tony Stark" heroName="Iron Man" />
			<Greet name="Steve Rogers" heroName="Captain America" />
			<Greet name="Bruce Banner" heroName="Hulk" />
        	</div>
)}

export default App;
  • 위의 경우  Greet라는 컴포넌트에 Name, heroName이라는 props로 값들이 들어가 있는 형태이다.
  • 자식 컴포넌트에서는 {props.props이름}의 형태로 사용된다.
function Greet(props) {
	return (
		<h1>Hello {props.name} a.k.a {props.heroName}</h1>
)}

// Hello Tony Stark a.k.a Iron Man
// Hello Steve Rogers a.k.a Captain America
// Hello Bruce Banner a.k.a Hulk
  • 아까 부모 컴포넌트에서 받은 props를 이렇게 사용했다.

3. 비구조화 할당을 이용한 사용법

function Greet({ name, heroName }) {
	return (
		<h1>Hello { name } a.k.a { heroName }</h1>
)}

// Hello Tony Stark a.k.a Iron Man
// Hello Steve Rogers a.k.a Captain America
// Hello Bruce Banner a.k.a Hulk
  • 위와 똑같이 작동하지만 조금 더 짧게 사용할 수 있다.

4. defaultProps

  • 컴포넌트에 따로 props를 안 정해놓고 어디서나 사용할 값을 설정할 수 있는 defaultProps를 설정할 수 있다.
  • 그럼 부모가 되는 App.js파일에는 props로 넘겨주려고 하는 값이 없을 것이다.
function Greet({ name, heroname }) {
	return (
		<h1>Hello {name} a.k.a {heroName}</h1>
)}

Greet.defaultProps = {
	name: 'No Name',
    heroName: 'No Heroname'
}

exprot default Greet;

4. 주의점

  • props는 '읽기 전용'이다. 컴포넌트 자체의 props를 수정할 수 없다. 즉 입력값을 변경해 버리면 안 된다.
COMMENT
 
07
11

1. 사건의 발단

  • 많은 사람들이 화살표 함수의 사용을 헷갈려하고 있다는 것을 알았다.
  • 어떻게 하는지 확실히 알면 보통 함수 작성봅 보다 매우 편하고 유용하다는 것을 알려주기 위해 글을 작성하게 되었다.

2. 화살표함수와 일반적 함수의 모양의 차이

const arr = [1, 2, 3, 4, 5]
const sum5 = arr.map(function(x) {
	return x + 5;
})
console.log(sum5) // [6, 7, 8, 9, 10]
  • 이것은 일반적 형태의 함수로 고차 함수 map을 사용한 것이다. 콜백 함수의 정보가 정확히 쓰여 있는 것을 알 수 있다.
const arr = [1, 2, 3, 4, 5]
const sum5 = arr.map(x => x + 5)
console.log(sum5) // [6, 7, 8, 9, 10]
  • 이것은 화살표 함수를 사용하여 고차함수  map을 사용한 것이다.
  • 둘의 가장 큰 차이로는 function이 없어지고 중괄호 안에 return 도 생략이 가능하다는 것이다. 그래서 더 짧게 사용할 수 있다.
  • 간단하게 그 두가지 다른 점과 위의 두 가지 방법의 map사용을 보면서 인자인 x의 위치, 화살표 함수가 반환하는 값을 생각해보면 다른 것도 쉽게 적용할 수 있다.
const arr = [1, 2, 3, 4, 5]
const sum5 = arr.map(x => {return x + 5}) // 중괄호가 있다.
console.log(sum5) // [6, 7, 8, 9, 10]
  • 이러한 형태도 가능하다. 나는 주로 map함수 안에 다른 함수를 넣거나 조건문 if를 넣는 등의 데이터 수정을 하려고 할 때 사용한다.

3. 또 다른 차이점

  • 가장 큰 장점이자 차이는 'this'의 사용이다.
  • this는 화살표 함수와 일반 함수에서 다르다.
  • 화살표 함수의 경우 this는 바로 위 상위 스코프의 this와 같다.
  • 일반 함수의 경우 this는 동적으로 바인딩 되어 내부 함수, 콜백 함수, 전역 객체, 객체의 메서드, 생성자 함수를 뜻한다.
  • 물론 콜백함수의 특성상 많이 겹쳐질 경우 코드를 작성한 사람도 헷갈려지는 경우가 있기 때문에 this를 남발하는 일은 지양하는 것이 좋다. 하지만 무엇을 뜻하는지 알고 있으면 유리하다.
위의 글은 그저, 빠르게 모양만을 가지고 화살표 함수를 바꿔 사용하는데 이해하기 위한 글이다. 화살표 함수의 사용을 자유롭게 한다고 해서 고차함수를 이해하게 되는 것은 아니므로, 고차함수의 사용을 해보면서 어떻게 사용하는것이 옳은가, 혹은 어떤 원리인가를 이해하면 자연스럽게 화살표 함수를 자주 사용하는 자신의 모습을 볼 수 있을 것이라고 생각한다.

 

COMMENT