• 카테고리

    질문 & 답변
  • 세부 분야

    프론트엔드

  • 해결 여부

    해결됨

setStatus, 콜백함수, 변수 스코프에 대해 질문드립니다.

23.11.14 20:39 작성 23.11.15 09:37 수정 조회수 169

0

강사님 안녕하세요
항상 상세한 답변을 주시는 점 감사드립니다.
아래의 코드를 보고 질문을 받아주시면 감사하겠습니다.

import './App.css';
import Counter from './Counter';
import Container from './Container';
import {useEffect, useState} from "react";
import MyHeader from './MyHeader.js'

export default function App() {
  const [state, setState] = useState({ a: 0, b: 0 });

  const onClick = () => {
    const c=10;
    setState(c=>({
      a: c + 1
    }));
  };

  return (
    <div className="App">
      <div>a : {state.a}</div>
      <button onClick={onClick}>증가</button>
    </div>
  );
}


1번째 경우
원래는 아래의 코드처럼 setState의 콜백함수의 인자에 state를 넣는 게 맞습니다.

const c=10;
 setState(state=>({
      a: c + 1  // 이 줄의 c는 1번째 줄의 c를 가리키므로 a: 10 + 1 과 같습니다.
    }));

이때는 a:c+1에서의 c가 함수 밖에 선언된 맨위의 const c= 10의 c를 가리킵니다.

 

2번째 경우
일부러 setState의 콜백함수의 인자를 state가 아닌 c로 적어봤습니다.

const c=10;
 setState(c=>({   //이 부분 변경 state 를 지우고 c로
      a: c + 1   // 이 줄에서의 c는 1번째 줄의 c를 가리키지 않습니다.
    }));

그러자 a: c + 1 에서의 c는 1번째 줄의 c가 아닌, 콜백함수 인자로 들어간 2번째 줄의 c를 가리킵니다.

그래서 변수의 스코프를 공부하고 싶어서 조언을 구하고 싶습니다.

 

1번째 질문을 드립니다.

변수가 const, let, var 인지에 따라서 스코프가 다른 것으로 아는데

콜백함수의 인자로 들어간 변수는 const인지 let인지, var 인지 질문드리고 싶습니다.

 

2번째 질문을 드립니다.

이 부분에 대해 학습하면 좋을 자료 링크를 추천해주시면 감사하겠습니다.

저도 현재 변수 스코프에 대해 다시 공부하는 중입니다.

3번째 질문을 드립니다.

const c=10;
 setState(c=>({   //이 부분 변경 state 를 지우고 c로
      a: c + 1   // 이 줄에서의 c는 1번째 줄의 c를 가리키지 않습니다.
    }));

 에서
2번째 줄의 콜백함수 인자의 c는
1번째 줄의 c를 가리키지 못하는 이유에 대해 질문드리고 싶습니다.

4번째 질문을 드립니다.
const c=10;
setState(state=>({ //이 부분 변경 state 를 지우고 c로
a: c + 1 // 이 줄에서의 c는 1번째 줄의 c를 가리키지 않습니다.
}));
3번째 줄의 c는 1번째 줄의 c를 가리킬 수 있는 이유에 대해 질문드리고 싶습니다

감사합니다.

답변 1

답변을 작성해보세요.

1

안녕하세요 이정환입니다.

함수 블록 내부에서 변수 스코프가 어떻게 작동하는지에 관련해 궁금한 점을 질문 주셨네요 순서대로 질문을 정리해주셨으니 저도 순서대로 답변해 드리겠습니다.

 

1번 질문

먼저 인자 라고 함은 함수 호출시 값을 전달하는 인수와 호출된 함수에서 값을 전달받는 매개변수를 아울러 통칭하는 단어로 알고 있습니다. 말씀해주신 인자인수를 뜻하는지 매개변수를 뜻하는지 조금은 헷갈리는데요 일단 매개변수라고 가정하고 답변해 드리겠습니다.

결론적으로 매개변수는 let 으로 선언된 변수라고 생각하심이 좋을 것 같습니다. var는 모던 자바스크립트에서는 잘 사용되지 않기에 용의 선상에서 아예 배제하셔도 됩니다. const가 아닌 이유는 다음 코드를 보시면 이해하실 수 있습니다.

function test(a) {
  a = 10;
  console.log(a);
}

test(1);
// 10 출력

위 코드의 실행 결과는 10입니다. 만약 test 함수의 매개변수 a가 const로 선언된 상수였다면 a=10 같은 동작이 허용되지 않았을 테니 매개변수 a는 let으로 선언된 변수와 동일하다 라고 이해해주시면 좋을 것 같습니다.

 

2번 질문

변수 스코프에 관한 자료는 너무 여기저기에 많이 존재해서요 하나의 자료에만 의존하시지 마시고 구글링을 통해 이런 저런 여러가지 자료들을 종합해 학습하시는걸 추천드립니다.

그럼에도 한가지만 추천드리자면 다음 링크를 통해 학습하시면 도움이 되실 겁니다.
(제 도서의 온라인 본입니다)

https://reactjs.winterlood.com/e4741df6-dffe-4324-8ffa-3d20f9f42ec5

 

3번 질문

자바스크립트의 스코프 규칙때문입니다. 자바스크립트는 변수를 참조할 때 현재 블록 부터 시작해 상위 블록으로 올라가며 변수를 찾습니다. 질문 주신 코드에서는 변수 c가 현재 블록에 위치하기 때문에 상위 블록의 const로 선언된 상수 c를 참조하지 않게 됩니다.

 

4번 질문

3번과 동일한 이유로 상위 블록의 상수 c를 참고합니다.

aalikesme님의 프로필

aalikesme

질문자

2023.11.15

강사님 상세한 답변 감사합니다
제가 궁금했던 부분이 아직 해결이 안되어서
하나만 더 질문을 드려도 되겠습니까?
const c=10;
setState(c=>({
a: 11
}));
일 때 콜백함수의 매개변수 c는
왜 상위 스코프의 c의 값인 10을 받지 못하는 것인지 질문드리고 싶습니다
자바스크립트는 변수를 참조할 때 현재 블록 부터 시작해 상위 블록으로 올라가며 변수를 찾기 때문에
상위 스코프 변수 c의 10을
하위 스코프의 변수 c도 받을 것이라고 생각했습니다.

안녕하세요 이정환입니다.

😃 질문이야 언제든 얼마든 환영입니다

const c=10; 
setState(c=>({ 
    a: 11 
}));

위 코드에서 setState의 콜백함수 내에서 c의 값이 10이 아닌 이유는 Scope의 Shadowing 때문입니다.

함수 안에서 밖에 선언된 같은 이름의 변수를 사용하는 경우 함수 밖의 변수를 잠시 가려두고 

해당 함수 안에 선언된 변수로만 인식해서 사용하는데요 이를 shadowing이라고 합니다!

aalikesme님의 프로필

aalikesme

질문자

2023.11.19

선생님 감사합니다