본문 바로가기

Front-End/React

[React] 230501 학습일기

http://www.yes24.com/product/goods/97782392

 

초보자를 위한 리액트 200제 (React) - YES24

따라하면서 이해하는 React A to Z리액트를 시작하기 전에 개발 환경을 준비하는 과정부터 시작하여 예제 파일을 실행하는 방법을 안내한다. 입문부터 초급, 중급, 활용, 실무까지 5개의 파트로 나

www.yes24.com

 

길고도 긴 무기력 상태를 벗어나 이젠 좀 열심히 살아보려 한다.

ㅋㅋ..ㅜㅜ


**  시작하기 전에 굉장한 것을 알아냈다.

R008_LifecycleEx.js 파일이 아래와 같고

import React,{Component} from "react";

class R008_LifecycleEx extends Component {
    constructor(props) {
        super(props);
        this.state = {};
        console.log('1. constructor Call');
    }

    static getDerivedStateFromProps(props, state) {
        console.log('2. getDerivedStateFromProps Call :'+props.prop_value);
        return {tmp_state:props.prop_value};
    }
    
    render() {
        console.log('3. render Call');
        return (
            <h2>[THIS IS shouldComponentUpdate FUNCTION]</h2>
        )
    }

    componentDidMount() {
        console.log('4. componentDidMount Call');
        console.log('5. tmp_state: '+this.state.tmp_state);
        this.setState({tmp_state2:true});
    }

    shouldComponentUpdate(props,state) {
        console.log('6. shouldComponentUpdate Call / tmp_state2= '+state.tmp_state2);
        return state.tmp_state2;
    }
}

export default R008_LifecycleEx;

App.js 파일이 아래와 같을 때

import React from 'react';
import './App.css';
import LifecycleEx from './R008_LifecycleEx';


function App() {
  return (
    <div>
      <h1>Start React 200!</h1>
      <p>CSS 적용하기</p>
      <LifecycleEx
        prop_value = 'FromApp.js'
      />  
    </div>
  );
}

export default App;

R008_LifecycleEx.js에서 export default로 내보낸 컴포넌트의 이름은 R008_LifecycleEx이지만

App.js에서 import할 때 이름은 그냥 LifecycleEx로 해줘도 되는 것이다.

 

왜 그런지 챗지피티쌤에게 물어보자.


Q. App.js에서 import R008_LifecycleEx from './R008_LifecycleEx’;라고 안 쓰고 import LifecycleEx from './R008_LifecycleEx'; 이렇게 써도 실행이 되는 이유는 뭐야?

A.

React 컴포넌트의 이름은 컴포넌트 클래스의 변수 이름이며, import 문의 별칭(alias)은 컴포넌트 클래스의 변수 이름과 무관합니다.

따라서, import 문에서 사용하는 이름(alias)은 해당 모듈에서 export하는 이름과 관련이 있으며, App.js에서 import R008_LifecycleEx from './R008_LifecycleEx';와 import LifecycleEx from './R008_LifecycleEx';는 동일한 결과를 가져옵니다.

, export default 구문을 사용하여 R008_LifecycleEx 클래스를 export한 경우, import 문에서 해당 클래스에 대해 원하는 이름(alias)을 사용할 수 있습니다.


App.js에서 Star(내가 임의로 설정한 이름)이라는 이름으로 가져와도 정상적으로 작동하는 것을 확인할 수 있다.

import React from 'react';
import './App.css';
import Star from './R008_LifecycleEx';


function App() {
  return (
    <div>
      <h1>Start React 200!</h1>
      <p>CSS 적용하기</p>
      <Star
        prop_value = 'FromApp.js'
      />  
    </div>
  );
}

export default App;

 

 

1. 템플릿 문자열 사용하기

 

  • ES: 표준화된 스크립트 언어
    • ES 뒤에 붙은 숫자는 버전을 의미
    • 자바스크립트는 ES6의 규격을 따름
    • react도 자바스크립트 기반의 언어이기 때문에 ES6의 모든 기능을 사용할 수 있음.

 

App.js를 아래와 같이 수정해보자.

 

import React from 'react';
import './App.css';
import Es6 from './R009_Es6'


function App() {
  return (
    <div>
      <h1>Start React 200!</h1>
      <p>CSS 적용하기</p>
      <Es6 />  
    </div>
  );
}

export default App;

 

R009_Es6.js를 생성하고 아래의 코드를 넣어보자.

import React,{Component} from "react";

class R009_Es6 extends Component {
    constructor(props) {
        super(props);
        this.state= {};
    }

    render() {
        return (
            <h2>[THIS IS ES6 STRING]</h2>
        )
    }

    componentDidMount() {
        let jsString1 = '자바스크립트';
        let jsString2 = '입니다\n다음줄입니다.';
        console.log(jsString1+' 문자열'+jsString2+'~');

        let Es6string1 = 'ES6';
        let Es6string2 = '입니다';
        console.log(`${Es6string1} 문자열${Es6string2}!!
___다음 줄입니다.`);

        let LongString = "ES6에 추가된 String 함수들입니다";
        console.log('startsWith: '+LongString.startsWith("ES6에 추가"));
        console.log('endsWith: '+LongString.endsWith("함수들입니다."));
        console.log('includes: '+LongString.includes("추가된 String"));
    }
}

export default R009_Es6;

  • 기존 자바스크립트에서 줄바꿈을 하려면 개행문자(\n) 을 사용해야 한다.
  • 문자열과 변수를 합치려면 문자열을 작은 따옴표(or 큰 따옴표)로 감싸고 +로 연결해야 함.
  • 따옴표가 아닌 백틱(`)으로 전체 문자열과 변수를 묶어 사용함. 
    • 변수는 ${변수명} 형태로 넣음
    • 이때 코드상에서 줄바꿈을 하면 개행 문자 없이도 사용할 수 있음.
  • startsWith(), endsWith(), includes() 는 ES6에 추가된 String 함수.
    • startsWith(): 변수 앞에서부터 일치하는 문자열이 있는지 찾음. ~로 시작하는지 안 하는지.
    • endsWith(): 변수 뒤에서부터 일치하는 문자열이 있는지 찾음. ~로 끝나느지 안 끝나는지.
    • includes(): 위치에 상관없이 변수에 특정 문자열이 포함되어 있는지 판단함.
    • 세 함수 모두 함수 조건에 부합하면 true, 부합하지 않으면 false를 반환

 


Q. javascript에서 백틱의 역할은 뭐야?

A.

백틱(backtick)은 ES6에서 도입된 문자열(string) 표기법 중 하나입니다.

백틱으로 묶인 문자열은 일반적인 따옴표(')나 쌍따옴표(")로 묶인 문자열과 유사하지만, 백틱 안에는 변수나 표현식을 삽입할 수 있습니다. 이를 Template Literal 또는 Template String이라고도 부릅니다.

예를 들어, 다음과 같이 변수를 삽입하여 문자열을 만들 있습니다.

const name = 'John';
const greeting = `Hello, ${name}!`;
console.log(greeting); // "Hello, John!"

또한, 여러 줄로 이루어진 문자열을 표현할 때도 유용합니다. 일반적인 따옴표나 쌍따옴표로는 줄바꿈 문자를 사용하여 여러 줄의 문자열을 만들 수 있지만, 이 경우에는 문자열 내의 공백과 줄바꿈이 그대로 포함됩니다.

하지만 백틱을 사용하면, 개행 문자나 문자 등의 공백도 그대로 유지됩니다.

const multiLineString = `
  This is a string
  that spans multiple lines.
  It even includes tabs:	like	this.
`;
console.log(multiLineString);
// "This is a string
//  that spans multiple lines.
//  It even includes tabs:	like	this."

 

2. var, let, const 사용하기

 

  • ES5의 var: 유연한 방식으로 변수를 재선언, 재할당 가능

=> 변수의 사용범위가 불확실해지거나 의도하지 않은 변숫값 변경이 발생할 수 있었음.

var의 단점을 보완하기 위해 ES6에서 let과 const 추가됨.

 

App.js를 수정해보자.

import React from 'react';
import './App.css';
import Variable from './R010_Variable'


function App() {
  return (
    <div>
      <h1>Start React 200!</h1>
      <p>CSS 적용하기</p>
      <Variable/>  
    </div>
  );
}

export default App;

R010_Variable.js 파일을 만들고 아래의 파일을 만들어보자.

import React,{Component} from "react";

class R010_Variable extends Component {

    constructor(props) {
        super(props);
        this.state = {};
    }

    render() {
        return (
            <h2>[THIS IS VARIABLE]</h2>
        )
    }

    componentDidMount() {
        var varName = 'react';
        console.log('varName1: '+varName);
        var varName = '200'; // 'varName' is already defined  no-redeclare
        console.log('varName2: '+varName);

        let letName ='react';
        console.log('letName1: '+letName);
        // let letName= '200';
        // Parsing error: Identifier 'letName' has already been declared. (25:12)
        letName ='react200';
        console.log('letName2: '+letName);

        const constName ='react';
        console.log('constName: '+constName);
        // const constName ='200';
        // Parsing error: Identifier 'constName' has already been declared. (31:14)
        // constName ='200';
        // Uncaught TypeError: Assignment to constant variable.
 
    }


}

export default R010_Variable;

 

아래의 코드들은 각각 warning과 error를 만들어낸다.

 

var varName = 'react';
console.log('varName1: '+varName);
var varName = '200'; // 'varName' is already defined  no-redeclare
console.log('varName2: '+varName);

이미 선언한 var 변수 varName을 다시 선언한 경우.

위와 같이 경고메시지가 출력된다.

하지만 var 변수는 재선언, 재할당을 허용하기 때문에 경고 메시지가 출력되어도 페이지가 정상적으로 표시됨.


let letName ='react';
console.log('letName1: '+letName);
let letName= '200'; // Parsing error: Identifier 'letName' has already been declared. (25:12)

이미 선언한 let 변수 letName을 다시 선언한 경우.

위와 같이 에러메시지가 뜬다.

let 변수는 재선언을 허용하지 않음.

 

그냥 웬만하면 재선언은 허용되지 않는다고 생각하면 편할 듯

 

let 변수는 재할당은 허용한다.

이미 선언한 let 변수에 새로운 값을 할당하는 것은 허용된다는 의미.


const constName ='react';
console.log('constName: '+constName);
const constName ='200'; // Parsing error: Identifier 'constName' has already been declared. (31:14)

이미 선언한 const 변수 constName을 다시 선언한 경우.

에러메시지가 출력됨.

const 변수는 재선언을 허용하지 않음.


const constName ='react';
console.log('constName: '+constName);
constName ='200'; // Uncaught TypeError: Assignment to constant variable.

이미 선언한 const 변수 constName에 새로운 값을 할당한 경우

에러메시지가 출력됨.

const 변수는 재할당을 허용하지 않음.

 

 

3. 전개 연산자 사용하기 => 배열과 객체의 데이터를 합치거나 추출하는 방법

 

전개연산자: 배열이나 객체 변수를 좀 더 직관적이고 편리하게 합치거나 추출할 수 있게 도와주는 문법

  • 변수 앞에 ...(마침표 3개)를 입력해 사용함.

 

App.js 를 수정하자.

import React from 'react';
import './App.css';
import SpreadOperator from './R011_SpreadOperator'

function App() {
  return (
    <div>
      <h1>Start React 200!</h1>
      <p>CSS 적용하기</p>
      <SpreadOperator/>
    </div>
  );
}

export default App;

 

R011_SpreadOperator.js 파일을 만들고 아래의 코드를 넣자.

import React, {Component} from "react";

class R011_SpreadOperator extends Component {
    constructor(props) {
        super(props);
        this.state = {};
    }

    render(){
        return (
            <h2>[THIS IS SPREADOPERATOR]</h2>
        )
    }

    componentDidMount() {
        var varArray1 = ['num1','num2'];
        var varArray2 = ['num3','num4'];

        //javascript Array(기존의 ES5)
        /** 기존 ES5에서 배열 2개를 합치기 위해서는 */
        var sumVarArr = [varArray1[0],varArray1[1],varArray2[0],varArray2[1]]; //배열 각각에 인덱스로 접근해 값을 가져오거나
        var sumVarArr = [].concat(varArray1,varArray2); //concat 함수를 사용한다. 
        console.log('1. sumVarArr: '+sumVarArr);

        //ES6 Array
        let sumLetArr = [...varArray1,...varArray2]; //ES6에서는 전개 연산자 ...(마침표 3개)을 배열명 앞에 붙여 여러개의 배열을 합칠 수 있음.
        console.log('2. sumLetArr: '+sumLetArr);

        const [sum1,sum2,...remain] = sumLetArr; 
        /** sumLetArr 배열의 값을 추출해 개별 변수에 넣음. 
         * 순서대로 변수 sum1에 sumLetArr[0]값, 변수 sum2에 sumLetArr[1]값을 대입
         * 나머지 배열값은 마지막에 전개 연산자 처리된 ...remain 변수에 넣음  */
        console.log('3. sum1: '+sum1+', sum2: '+sum2+', remain: '+remain);


        var varObj1 ={key1:'val1',key2:'val2'};
        var varObj2 ={key2:'new1',key3:'val3'};

        //javascript Object
        /** 기존 ES5에서 객체 2개를 합치기 위해서는*/
        var sumVarObj = Object.assign({},varObj1,varObj2); //Object.assign() 함수를 이용해야 함.
        /** 첫번째 인자 {}는 함수의 return값이고 뒤의 인자에 객체들을 ,(콤마)로 연결해 나열하면 여러개의 객체를 합칠 수 있음*/
        console.log('4. sumVarObj: '+JSON.stringify(sumVarObj)); 

        //ES6 Object
        var sumLetObj = {...varObj1, ...varObj2};
        console.log('5. sumLetObj: '+JSON.stringify(sumLetObj))

        var {key1,key3,...others} = sumLetObj;
        /** sumLetObj 객체의 키와 값을 추출해 키와 동일한 명칭의 개별 변수에 넣음
         * 나머지는 마지막에 전개 연산자 처리된 ...others 변수에 넣음 */
        console.log('6. key1: '+key1+', key3: '+key3+', others: '+JSON.stringify(others));
    }
}

export default R011_SpreadOperator;

Q. JSON.stringify가 뭐야?

A.

JSON.stringify()는 JavaScript 객체나 배열을 JSON 문자열로 변환하는 메소드입니다.

JavaScript 객체는 {} 중괄호 안에 key-value 쌍으로 데이터를 저장할 수 있습니다. 이때, key는 문자열이어야 하고, value는 문자열, 숫자, 불리언, 객체, 배열 등 다양한 타입이 올 수 있습니다.

JSON 문자열은 JavaScript 객체와 유사한 형태를 가지며, JSON 형식의 데이터를 서버와 주고받거나 파일에 저장할 때 자주 사용됩니다. JSON.stringify() 메소드는 이러한 JavaScript 객체를 JSON 문자열로 변환하여 저장하거나 전송할 수 있도록 도와줍니다.

예를 들어, 다음과 같은 JavaScript 객체를 JSON.stringify() 메소드를 사용하여 JSON 문자열로 변환할 있습니다.

const data = {
  name: "John",
  age: 30,
  isStudent: false,
  hobbies: ["reading", "swimming"]
};

const jsonString = JSON.stringify(data);
console.log(jsonString);
// 출력 결과: {"name":"John","age":30,"isStudent":false,"hobbies":["reading","swimming"]}

이와 같이 JSON.stringify() 메소드를 사용하면 JavaScript 객체나 배열을 JSON 문자열로 변환할 있습니다.


Q. javascript에서 concat 함수는?

A.

concat() 함수는 배열에 새로운 요소를 추가하여 새로운 배열을 생성하는 JavaScript 배열 메소드 중 하나입니다.

concat() 함수는 원본 배열을 변경하지 않고, 새로운 배열을 반환합니다. 이 새로운 배열은 원본 배열과 concat() 함수에 전달된 인수들을 합친 결과입니다. 인수로 전달된 값은 배열이 아닌 경우에도 배열로 변환되어 새로운 배열에 추가됩니다.

concat() 함수는 여러 개의 배열을 합치거나, 배열과 다른 값을 함께 합칠 때 유용하게 사용됩니다.

예를 들어, 다음과 같은 배열이 있다고 가정해보겠습니다.

const arr1 = [1, 2, 3];
const arr2 = [4, 5, 6];

이때, concat() 함수를 사용하여 arr1arr2를 합칠 수 있습니다.

const arr3 = arr1.concat(arr2);
console.log(arr3);
// 출력 결과: [1, 2, 3, 4, 5, 6]

concat() 함수는 인수로 전달된 배열을 순서대로 합치기 때문에, 첫 번째 배열의 끝에 두 번째 배열이 이어져서 합쳐진 결과가 출력됩니다. 이와 같이 concat() 함수를 사용하여 여러 개의 배열을 합칠 수 있습니다.

concat() 함수를 사용하여 배열과 다른 값을 함께 합칠 때 다음과 같이 사용할 있습니다.

const arr4 = arr1.concat("hello", 7);
console.log(arr4);
// 출력 결과: [1, 2, 3, "hello", 7]

이와 같이 concat() 함수를 사용하면 배열과 다른 값을 함께 합칠 있습니다.


Q. Object.assign 함수는 뭐야?

A.

Object.assign()은 JavaScript에서 사용되는 객체 메소드 중 하나로, 하나 이상의 소스 객체로부터 대상 객체로 속성을 복사하는 데 사용됩니다.

대상 객체(target)는 첫 번째 인수로 전달되며, 소스 객체(source)는 두 번째 인수부터 마지막 인수까지 전달됩니다. 복사는 소스 객체의 열거 가능한 모든 속성에 대해 수행됩니다. 중복된 속성이 있을 경우 나중에 전달된 소스 객체의 속성 값으로 덮어씁니다.

Object.assign()은 대상 객체를 반환합니다.

예를 들어, 다음과 같은 개의 객체가 있다고 가정해보겠습니다.

const obj1 = { a: 1, b: 2, c: 3 };
const obj2 = { b: 4, c: 5, d: 6 };

이때, Object.assign() 함수를 사용하여 obj1 객체와 obj2 객체를 합칠 있습니다.

const newObj = Object.assign(obj1, obj2);
console.log(newObj);
// 출력 결과: { a: 1, b: 4, c: 5, d: 6 }

위 코드에서, Object.assign() 함수는 obj1 객체와 obj2 객체를 합쳐서 newObj 객체를 만들고, newObj 객체를 반환합니다. obj1 객체와 obj2 객체에 동일한 속성이 있을 경우, obj2 객체의 속성 값으로 덮어씁니다. 따라서 결과 객체에서 b와 c 속성의 값은 obj2 객체의 값이 됩니다. => 이때 obj1도 newObj와 동일하게 변경됨.

 

Object.assign() 함수를 사용하여 복사를 할 수도 있습니다. 이때는 번째 인수로 객체를 전달하면 됩니다.

const obj3 = { a: 1, b: 2, c: 3 };
const emptyObj = Object.assign({}, obj3);
console.log(emptyObj);
// 출력 결과: { a: 1, b: 2, c: 3 }

코드에서, Object.assign() 함수는 객체({}) obj3 객체를 복사하여 emptyObj 객체를 만듭니다.

 


Q. const newObj = Object.assign(obj1, obj2); 랑 const newObj = Object.assign({},obj1, obj2); 랑 똑같은거 아니야?

A. 

const newObj = Object.assign(obj1, obj2);와 const newObj = Object.assign({}, obj1, obj2);는 다릅니다.

Object.assign() 함수의 첫 번째 인수로 전달되는 객체는 결과값이 저장될 대상 객체가 됩니다. 따라서, const newObj = Object.assign(obj1, obj2);와 같이 첫 번째 인수로 obj1을 전달하면, obj1 객체에 obj2 객체의 속성이 추가되어 반환됩니다. 이때, obj1 객체는 변경된 상태로 유지됩니다.

반면에, const newObj = Object.assign({}, obj1, obj2);와 같이 첫 번째 인수로 빈 객체 {}를 전달하면, 새로운 객체가 생성되어 obj1과 obj2 객체의 속성이 병합된 결과가 반환됩니다. 이때, obj1과 obj2 객체는 변경되지 않습니다.

예를 들어, 다음과 같은 객체가 있다고 가정해보겠습니다.

const obj1 = { a: 1 };
const obj2 = { b: 2 };

이때, Object.assign() 함수를 사용하여 객체를 병합할 있습니다.

const newObj1 = Object.assign(obj1, obj2);
console.log(newObj1);  // 출력 결과: { a: 1, b: 2 }
console.log(obj1);     // 출력 결과: { a: 1, b: 2 }
console.log(obj2);     // 출력 결과: { b: 2 }
obj1.a = 3;
console.log(newObj1);  // 출력 결과: { a: 3, b: 2 }
console.log(obj1);     // 출력 결과: { a: 3, b: 2 }

코드에서, Object.assign(obj1, obj2) 함수는 obj1 객체에 obj2 객체의 속성을 추가하여 새로운 객체를 만듭니다. 이때, newObj1 객체와 obj1 객체는 동일한 객체를 참조하므로, obj1 객체가 변경되면 newObj1 객체도 변경됩니다.

코드에서, obj1 객체의 a 속성의 값을 변경하면, newObj1 객체도 변경됩니다.

 

 

이제, Object.assign({}, obj1, obj2) 함수를 사용하여 객체를 병합해보겠습니다.

const newObj2 = Object.assign({}, obj1, obj2);
console.log(newObj2);  // 출력 결과: { a: 3, b: 2 }
console.log(obj1);     // 출력 결과: { a: 3 }
console.log(obj2);     // 출력 결과: { b: 2 }
obj1.a = 1;
console.log(newObj1);  // 출력 결과: { a: 3, b: 2 }
console.log(obj1);     // 출력 결과: { a: 1 }

객체를 전달하여 새로운 객체를 만들어주므로 원본 객체인 obj1 obj2 변경하지 않으면서 객체를 병합하여 새로운 객체 newObj 생성할 있습니다.

 

 

4. class 사용하기

 

  • 객체 구현 in 기존의 ES5 자바스크립트: prototype 사용
  • 객체: 상속을 통해 코드를 재사용할 수 있게 해줌.
  • ES6에서 등장한 class 는 prototype과 비슷한 개념.
    • 쉽게 읽고 표현하기 위해 고안됨.

App.js를 수정하자.

import React from 'react';
import './App.css';
import ClassPrototype from './R012_Class&Prototype';

function App() {
  return (
    <div>
      <h1>Start React 200!</h1>
      <p>CSS 적용하기</p>
      <ClassPrototype />
    </div>
  );
}

export default App;

 

 

R012_Class&Prototype.js 파일을 생성하고 아래의 코드를 넣어주자.

/** class */
import React,{Component} from "react";

class ClassPrototype extends Component {
    constructor(props) {
        super(props);
        this.state= {};
    }
    
    render() {
        return (
            <h2>[THIS IS CLASS]</h2>
        )
    }

    componentDidMount() {
        //ES5 prototype
        var ExamCountFunc = (function () { //자바스크립트에서는 함수를 객체로 사용할 수 있음
            function ExamCount(num) { //생성자함수(ExamCount) 실행
                this.number = num; //파라미터로 전달받은 num 변수의 값(200)을 객체 변수(number)에 저장.
            };

            ExamCount.prototype.showNum = function () { //
                /** 생성자함수명.prototype.함수명 형태로 선언해주면, 
                 * 객체 외부에서 함수(cnt.showNum();)를 실행해 객체 내부에 선언된 함수로 사용할 수 있음 
                 * 함수가 실행되면, 생성자 함수에서 '200'으로 할당된 객체 변수 number를 사용함.*/
                console.log('1. react_'+ this.number);
            };
            return ExamCount;
        } () );
        
        var cnt = new ExamCountFunc('200'); //ExacmCountFunc() 함수(객체)를 실행한 후 return되는 결괏값(객체)를 cnt라는 변수에 저장.
        cnt.showNum(); //객체 안에 선언된 showNum()함수 실행


        //ES6 class
        class ExamCountClass { //ES6에서는 객체를 class로 선언함.
            constructor(num2) { //constructor()이라는 생성자 함수가 실행됨.
                this.number2 = num2; //파라미터로 전달받은 num2 변수값(2hundred)을 객체 변수 number2에 저장.
            }
            showNum() { //객체에 접근할 때 실행할 함수 //class의 괄호 {}안에 간단하게 선언할 수 있음.
                console.log(`2. react_${this.number2}`); //생성자 함수에서 '2hundred'로 할당된 객체변수 number2를 사용
            }
        };
         var cnt2 = new ExamCountClass('2hundred'); //ExamCountClass 객체를 생성한 후 객체를 cnt2라는 변수에 저장.
         cnt2.showNum(); //객체 안에 선언된 showNum() 함수를 실행
    }

}

export default ClassPrototype;

 


Q.

var ExamCountFunc = (function () { //자바스크립트에서는 함수를 객체로 사용할 수 있음
            function ExamCount(num) { //생성자함수(ExamCount) 실행
                this.number = num; //파라미터로 전달받은 num 변수의 값(200)을 객체 변수(number)에 저장.
            };

            ExamCount.prototype.showNum = function () { //
                /** 생성자함수명.prototype.함수명 형태로 선언해주면, 
                 * 객체 외부에서 함수(cnt.showNum();)를 실행해 객체 내부에 선언된 함수로 사용할 수 있음 
                 * 함수가 실행되면, 생성자 함수에서 '200'으로 할당된 객체 변수 number를 사용함.*/
                console.log('1. react_'+ this.number);
            };
            return ExamCount;
        } () );

여기서 마지막 줄에 () 한번 더 써주는 이유는 뭐야?

A.

마지막 줄에 ()를 또 써주는 것은 즉시 실행 함수(IIFE)를 사용하고 있기 때문입니다.

즉시 실행 함수선언과 동시에 즉시 실행되는 익명 함수를 의미합니다. 이때 익명 함수를 괄호로 감싸준 뒤, 뒤에 다시 괄호를 붙여 함수를 호출하는 형태로 사용합니다. 이렇게 하면 함수를 정의한 뒤 바로 실행할 수 있으므로, 코드를 간결하게 작성할 수 있고 전역 스코프를 오염시키지 않아 안전합니다.

예제에서는 ExamCountFunc 변수에 즉시 실행 함수의 반환값인 생성자 함수 ExamCount를 할당하고 있습니다. 이때 ExamCountFunc 변수는 ExamCount 생성자 함수를 가리키게 됩니다. 함수를 즉시 실행함으로써 ExamCountFunc 변수에는 생성자 함수 ExamCount가 할당되고, 생성자 함수를 사용하여 ExamCount 객체를 생성 있습니다.


Q. 그러면 여기서는 ExamCount 객체를 선언해준다고 해야해? 아님 ExamCountFunc 객체를 선언해준다고 해야해?

A.

여기서 var ExamCountFunc는 생성자 함수를 반환하는 함수 표현식을 할당한 변수입니다. 따라서 ExamCountFunc는 생성자 함수가 아니라, 생성자 함수를 반환하는 함수입니다.

그리고 ExamCount ExamCountFunc 함수에서 반환된 생성자 함수입니다. var cnt = new ExamCount(200) 같이 ExamCount 생성자 함수를 사용하여 객체를 생성할 있습니다.(=> 이렇게는 써줄 수 없음)

 


Q. var cnt = new ExamCountFunc('200'); 이렇게 하면 안돼? (책에서 소개한 객체 생성법)

A.

`var cnt = new ExamCountFunc('200');` 이 코드는 `ExamCountFunc` 함수를 호출하여 반환된 객체를 `cnt` 변수에 할당하는 코드입니다. `ExamCountFunc` 함수 내부에서는 `ExamCount` 생성자 함수를 실행하여 새로운 객체를 생성하고, 그 객체의 `number` 속성에는 전달된 `num` 값이 저장됩니다. 그리고 `ExamCount` 객체의 `prototype` 속성에 `showNum` 함수가 추가됩니다.

따라서 이 코드는 `ExamCount` 객체가 아닌 `ExamCountFunc` 함수에서 생성한 객체를 `cnt` 변수에 할당하는 코드이므로, 코드의 의도와 다르게 작동합니다. `ExamCount` 객체를 생성하려면 `new ExamCount('200')` 과 같이 `ExamCount` 생성자 함수를 직접 호출해야 합니다.

 

=> 

var cnt = new ExamCount(200)

책에 나온 것과 다르게 이렇게 써주면

cnt.showNum()을 해줄 수 없음.

 

var cnt= new ExamCount(200);
cnt.showNum();

중간에 이렇게 바꿔서 실행하면

ExamCount가 정의되지 않았다고 한다.

역시 안된다.

 

 

5. 화살표 함수 사용하기

화살표 함수:

  • ES6에서 등장
  • 'function' 대신 '=>' 문자열을 사용하며 'return' 문자열을 생략할 수 있음.

→ 기존 ES5 함수보다 간략하게 선언 가능

  • callback 함수에서 this를 bind해야 하는 문제도 발생하지 않음.

자 근데 난관이다.

난 callback 함수가 뭔지 모른다;;

그래서 일단 물어봤다.


Q. 콜백 함수가 뭐야?

A.

콜백 함수(callback function)는 다른 함수의 인수(argument)로 전달되어 특정 로직이나 기능을 실행하는 함수를 말합니다. 

예를 들어, 어떤 작업을 하는 함수가 있다면 그 함수에 인수로 다른 함수를 전달하여 작업이 끝나면 전달된 함수를 실행하도록 할 수 있습니다. 이때 전달된 함수를 콜백 함수라고 부릅니다.

콜백 함수는 비동기적인 작업에서 많이 사용됩니다. 예를 들어, 파일을 읽어들이는 함수에 콜백 함수를 전달하여 파일 읽기가 완료되면 콜백 함수가 실행되도록 할 수 있습니다. 이렇게 하면 파일을 읽는 동안 다른 작업을 계속할 수 있습니다. 

콜백 함수는 자바스크립트에서 매우 중요한 개념 중 하나이며, 자바스크립트의 비동기적인 동작 방식에서 핵심적인 역할을 수행합니다.

 


근데 더 모르겠는 거다.

그래서 아래의 두 영상을 순서대로 봤다.

https://youtu.be/-iZlNnTGotk

https://youtu.be/U42qWURR6Gw

이 두개를 보니까 챗 지피티의 답변이 이해가 된다.


다시 돌아와서 

"callback 함수에서 this를 bind해야 하는 문제도 발생하지 않음."

이건 무슨 의미일까

 


Q. 자바스크립트에서 화살표 함수의 특징이 callback 함수에서 this를 bind해야하는 문제가 발생하지 않는다는 건데 이게 무슨 의미야?

A.

화살표 함수의 특징 중 하나는 this가 바인딩되는 방식이 일반 함수와 다르다는 것입니다.

일반 함수에서는 함수를 호출하는 방법에 따라 this 달라질 있습니다. 이때, callback 함수에서 this를 사용하게 될 경우, this가 예상한 대상과 다르게 바인딩될 가능성이 있습니다. 예를 들어, 아래와 같이 객체 내부의 함수를 callback 함수로 사용할 경우, this는 전역 객체를 가리키게 됩니다.

const obj = {
  name: 'Alice',
  sayName: function() {
    console.log(this.name);
  }
};

setTimeout(obj.sayName, 1000); // "undefined" 출력

하지만 화살표 함수에서는 함수를 선언할 this 바인딩되는 방식이 다릅니다. 화살표 함수에서 this는 언제나 상위 스코프의 this를 참조하게 됩니다. 따라서 화살표 함수를 callback 함수로 사용하게 될 경우, this가 상위 스코프의 this와 같게 바인딩되어 예상한 대로 동작하게 됩니다.

const obj = {
  name: 'Alice',
  sayName: function() {
    console.log(this.name);
  }
};

setTimeout(() => obj.sayName(), 1000); // "Alice" 출력

이러한 이유로, 화살표 함수를 사용하면 callback 함수에서 this bind해야하는 번거로움이 사라지게 됩니다.

 

아주 신기하다.


내친 김에 setTimeOut 함수에 대해서도 물어보자.


 

Q. setTimeOut 함수는 무슨 함수야?

A. 

setTimeout 함수일정 시간이 지난 후에 콜백 함수를 실행하도록 예약하는 JavaScript 내장 함수입니다.

setTimeout 함수는 다음과 같은 구문을 가집니다.

setTimeout(callback, delay, arg1, arg2, ...)
  • callback: 실행할 콜백 함수
  • delay: 콜백 함수를 실행하기 전에 기다려야 할 시간(밀리초 단위)
  • arg1, arg2, ... : 콜백 함수에 전달할 인자 (선택적)

setTimeout 함수는 주로 비동기적인 코드 실행을 구현할 때 사용됩니다. 예를 들어, 특정 시간이 지난 후에 어떤 작업을 수행하거나, 사용자의 입력이 끝난 후에 검색 결과를 표시하는 등의 상황에서 사용될 있습니다.

 


 

'Front-End > React' 카테고리의 다른 글

[React] useMemo  (0) 2023.12.27
[React] Describing the UI  (0) 2023.06.05
[React] 220423 학습일기  (0) 2023.04.24
[React] 220416 학습일기  (1) 2023.04.17
[ReactJS] 코드 모음  (0) 2023.04.03