Notice
Recent Posts
Recent Comments
Link
«   2025/03   »
1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30 31
Archives
Today
Total
관리 메뉴

성빈

React를 위한 자바스크립트2 본문

React

React를 위한 자바스크립트2

성빈나 2023. 10. 30. 13:06

목차

  • 객체와 배열
    • 구조분해 할당
    • 객체 리터럴
    • 스프레드 연산자
  • 비동기 자바스크립트
  • 클래스

객체와 배열

ES2016부터 객체와 배열을 다루는 방법과 객체와 배열 안에서 변수의 영역을 제한하는 방법을 다양하게 제공하기 시작했다. 이런 기능으로는 구조 분해, 객체 리터럴 개선, 스프레드 연산자 등이 있다.

 

구조분해 할당

구조 분해(destructuring )

객체 안의 필드, 배열을 구성하는 원소를 변수에 쉽게 대입할 수 있도록 활용

객체의 속성과 변수의 이름이 같다면, 구조분해 할당이 가능하다.

 

두 변수를 변경해도 원래의 필드 값이 비뀌지는 않는다. 

 

sandwich.bread, sandwich.meat 와 같이 나타내도 기존 객체를 참조하게 되지만, 매법 객체를 써서 나타내기 힘들다.

 

 

● 객체의 구조분해 할당

const { var_name } = object_name;

 

  •   객체를 인자로 받는 함수 

regularPerson 의 객체를 인자로 받아서 출력한다. 

 

 

  • 객체 인자 구조분해

* 주의 : ( { firstname } ) 에서 괄호를 생략하면 안된다 → 의미가 달라지기 때문

 

 

● 배열의 구조분해 할당

   원소를 변수에 각각 복제해서 사용하고 싶을 때 배열의 구조분해 할당을 사용한다. 

   순서에 주의해야한다. 

 

(예제 1)

원소는 3개이지만, 구조분해 할당 변수는 1개이다.

따라서 가장 첫번째 원소값만 저장하여 firstResort는 배열의 첫번째 인덱스인 '용평'을 가리킨다. 

 

 

(예제 2)

 

여러개의 값을 각각 대입하고자 할 때에는 원소에 맞게 변수를 할당해야한다. 

const [,,thirdResort] = ["용평","평창","강촌"] 와 같이 한 문장으로 표시도 가능하다.

 

* 리스트 매칭(list matching) : 불필요한 변수를 콤마(,)를 사용해 생략하는 것

 

 

객체 리터럴

구조 분해의 반대라고 할 수 있다.

구조를 다시 만들어내는 과정 또는 내용을 한데 묶는 과정이라 할 수 있다.

이를 사용하면 현재 영역에 있는 변수를 객체의 필드로 묶을 수 있다. 

 

● 예전 방식의 객체 리터럴

미리 변수를 생성한 후 객체의 속성으로 활용 가능하다. 

const name = "Julia Mancuso"
const sound = "go-fast"

// 객체를 선언하는 구문
var skier = {
	// 속성 선언
	name: name,
    sound: sound,
    // 함수 선언
    powderYell : function() {
    	var yell = this.sound.toUpperCase()
        console.log(`${yell} ${yell} ${yell}!!!`)
    },
    speed: function(mph) {
    	this.speed =  mph
        console.log('속력(mph):', mph)
    }
 }
 
 skier.powderYell()
 skier.speed(350)
 console.log(JSON.stringify(skier))

 

● 객체 리터럴 개선(object literal engancement)


예전의 방식과 달라지게 생략 가능한 부분이 있다. 


1.  속성과 할당할 변수가 이름이 같으면, 속성만 명시 가능하다.
      - 값을 찾아서 자동으로 할당해주기 때문이다.
      - 만약 변수를 그대로 활용하지 않을거면, 과거 방식처럼 뒤에 값을 추가해줘야한다. 
2. 메서드 선언 시, function 키워드를 생략할 수 있다.

 

 

 

스프레드 연산자

3개의 점(...)으로 이루어진 연산자로 아래 몇 가지 다른 역할을 담당한다.

 

1. 모든 원소를 나열한다.

 

모든 원소를 나열해서 하나의 변수를 만들었다.

peaks와 canyons에 포함된 모든 원소가 seoraksan이라는 새 배열에 들어간다. 

 

 

 

 

2. 배열의 원소들을 복사해서 사용하기 때문에, 원본은 변경되지 않는다.

    따라서 나중에 필요할 때 그것을 다시 사용할 수 있다. 

 

( 원본을 사용한 예 )

reverse() 메소드는  peaks 원본 배열을 변형했다는 것을 알 수 있다.

 

 

( 스프레드 연산자를 사용해 사본을 사용한 예 )

peaks를 스프레드 연산자로 복사한 후 reverse( ) 메소드를 수행했다.

따라서 사본에 reverse를 적용했기 때문에 원본은 영향을 받지 않는다. 

 

 

 

3. 배열의 나머지 원소들을 얻을 수 있다.

function directions(...args) {
	var [start, ...remaining] = args
    var [finish, ...stops] = remaining.reverse()
    
    console.log(`${args.length} 도시를 운행합니다.`)
    console.log(`${start}에서 출발합니다.`)
    console.log(`목적지는 ${finish}입니다.`)
    console.log(`중간에 ${stop.length}군데 들립니다.`)
}
directions("서울","수원","천안","대전","대구","부산")

...args = [서울, 수원, 천안, 대전, 대구, 부산]

start = 서울

...remaining = [수원, 천안, 대전, 대구, 부산]

remaining.reverse() = [부산, 대구, 대전, 천안, 수원]

finish = 부산

stops = [대구, 대전, 천안, 수원]

 

함수 파라미터 정의에서 스프레드 연산자가 쓰일 때는 rest parameter(나머지 원소들)라고 부른다. 

 

 

4. 스프레드 연산자를 객체에도 사용할 수 있다.

 

* morning으로 변경했을 때의 결과 

 

 


비동기 자바스크립트

먼저 예제 문제를 통해 알아보겠다.

 

(예제) 3개의 텍스트 파일을 순서대로 읽어와 콘솔에 출력하는 프로그램 구현

 

 

동기적인 자바스크립트 코드 

일련의 명령이 순서대로 실행된다.

 

비동기적인 자바스크립트 

code1 (랜덤으로 출력)

const fs = require('fs');
console.log('start');

fs.readFile('./readme1.txt', (err, data) => { //  콜백함수 1
	if(err)
    		console.error(err);
	else
    	console.log('lst reading: ', data.toString());
});
fs.readFile('./readme2.txt', (err, data) => { //  콜백함수 2
	if(err)
    	console.error(err);
    	else
    		console.log('2nd reading: ', data.toString());
});
fs.readFile('./readme3.txt', (err, data) => { //  콜백함수 3
	if(err)
    	console.error(err);
    	else
	    	console.log('3rd reading: ', data.toString());
});
console.log('end');

결과 : 랜덤으로 출력된다.

▶ 문제점  

    - 오래 걸린다.

    - 마냥 기다리게면 다음 작업을 진행 못한다.

    - 오랜 기간 응답없이 기다려야 한다.

 

 

 

code2 (callback 안에 callback)

const fs = require('fs');
console.log('start');

fs.readFile('./readme1.txt', (err, data) => {
	if(err)
		console.error(err);
	else {
		console.log('1st reading: ', data.toString());
		fs.readFile('./readme2.txt', (err, data) => {
			if(err)
				console.error(err);
			else {
				console.log('2nd reading: ', data.toString());
				fs.readFile('./readme3.txt', (err, data) => {
					if(err)
						console.error(err);
					else 
						console.log('3rd reading: ', data.toString());
					console.log('end');
				});
			}
		});
	}
});

결과 : 위의 작업이 처리되어야만 다음 구문 안으로 들어올 수 있기 때문에 순차적으로 출력된다.

문제점 : callback 안에 callback → 코드의 가독성이 떨어진다.

 

 

code3 (promise)

const fs = require('fs');

const promise = new Promise( (resolve, reject) => {
	console.log('start');
	fs.readFile('./readme1.txt', (err, data) => {
		if(err)
			reject(err);
		else
			resolve(data);
	})
})

promise
.then(data => {
	console.log('lst reading: ", data.toStrig());
	return new Promise( (resolve, reject) => {
    	fs.readFile('./readme2.txt', (err, data) => {
			if(err)
				reject(err);
			else
				resolve(data);
		});
	});
})
.then(data => {
	console.log('2nd reading: ", data.toStrig());
	return new Promise( (resolve, reject) => {
    	fs.readFile('./readme3.txt', (err, data) => {
			if(err)
				reject(err);
			else
				resolve(data);
		});
	});
})
.then(data => console.log('3rd reading: ', data.toString()))
.catch(err => console.error(err.message))
.finally(() => console.log('end'));

 결과 : promise로 콜백지옥 해결 가능하다.

 

 

 

promise

미래에 어떤 결과가 올지 모르겠지만, 그때를 대비해서 미리 결과를 예상하고 수해해야하는 로직들을 구현할 때 사용한다. 

  • 비동기 방식으로 실행하지만, 아직 결과를 반환하지 않은 객체
    • 성공: resolve(value)는 .then으로 연결
    • 실패 : rejected(value)는 .catch로 연결

 

  • 미래의 어떤 시점에 결과를 제공하겠다는 약속
    • 비동기 연산 종료 후 결과와 실패에 대한 처리기로 활용
const condition = true;
console.log('hello');

const promise = new Promise(resolve, reject) => {
	if(condition)
		resolve('success');
	else
		reject('fail);
});
console.log('world');

promise
.then(message => { // 성공 - resolve와 연결
	console.log(message);
})
.catch(err => { // 실패 - rejected와 연결
	console.error(err); 
})
.finally(() => { // 무관하게 수행
	console.log('default');
});

 

 

code 4 (fs 객체)

promise를 사용하는 것보다 간결하게 하기 위해, fs 객체를 활용한다. 

const fs = require('fs');
const fsPromises = fs.promises;

console.log('start');

fsPromises.readFile(./readme1.txt')
.then(data => {
	console.log('1st reading: ', data.toString());
	return fsPromises.readFile(./readme2.txt');
})
.then(data => {
	console.log('2nd reading: ', data.toString());
	return fsPromises.readFile('./readme3.txt);
})
.then(data => console.log('3rd reading: ', data.toString()))
.catch(err => console.error(err.message))
.finally(() => console.log('end'))

▶ 결과

      - 콜백함수를 지정하지 않아도 되기 때문에 코드가 간결해진다.
      - 파일을 읽었으면, 읽은 내용이 파라미터로 전달되어 바로 내용을 출력할 수 있다. 

      - .then .catch를 바로 연달아서 사용할 수 있다. (promise chaining)

 

 

fs 모듈의 readfile()   vs  fs.promises의 reafile()

• fs 모듈의 readfile()
  : readfile()안에 콜백함수를 파라미터로 추가할 수 있다.

• fs.promises의 reafile()
  : 콜백함수를 지정하지 않아도 바로 .then .catch 구문으로 바로 연결할 수 있다.

 

 

code5 (async & await 구문)

async 함수는 파라미스 다음에 있는 코드를 실행하기 전에 프라미스가 끝날 때까지 기다리라고 명령하는 것

await 함수는 프라미스가 완료될 때까지 순서대로 기다렸다가 처리하겠다는 구문

const fs = require('fs');
const fsPromises = fs.promises;

console.log('start');
(async () => {
	try {
		let data = await fsPromises.readFile('./readme1.txt');
		console.log('1st reading: ', data.toString());
		
		data = await fsPromises.readFile('./readme2.txt');
		console.log('2nd reading: ', data.toString());
        
		data = await fsPromises.readFile('./readme3.txt');
		console.log('3rd reading: ', data.toString());
	}
	catch(err){
		console.error(err.message);
	}
	finally{
		console.log('end');
	}
}) ();

 

 

code 6 (동기: readFileSync)

const fs = require('fs');
console.log('start');

try {
	let data = fs.readFileSync('./readme1.txt');
	console.log('1st reading: ', data.toString());
    
	data = fs.readFileSync('./readme2.txt');
	console.log('2nd reading: ', data.toString());
    
	data = fs.readFileSync('./readme3.txt');
	console.log('3rd reading: ', data.toString());
}
catch(err){
	console.error(err.message);
}
fianlly{
	console.log('end');
}

▶ 결과 : 오래 걸리는 작업이라도, 다른 작업을 미리 할 수 없다.

 

 

비동기 자바스크립트 : promise, fetch

  • promise
const getFakeMembers = count => new Promise((resolves, reject) => {
	const api = `https://api.randomuser.me/?nat=US&results=${count}`
	const request = new XMLHttpRequest()
	request.open('GET', api) // URL에 자원을 요청
	request.onload = () => 
		(request.status === 200) ? resolves(JSON.parse(request.response).results) :reject(Error(request.statusText))
        request.onerror = (err) => rejects(err)
		request.send()
})

getFakeMembers(5).then(
	members => console.log(members),
	err => console.error(
		new Error("randomuser.me에서 멤버를 가져올 수 없습니다."))
)

 

  • fetch문
fetch("https://api.randomuser.me/?nat=US&results=10") //URL로부터 데이터를 받음

.then(res => res.json()) // response를 json 형태로 변환
.then(json => json.results) // 객체의 results 속성 변환
.then(console.log) // console에 데이터 출력
.catch(console.error) // 에러시 console 에러 출력

 

 

비동기 자바스크립트 : async/await

const getFakeMembers = async () => {
    try {
        let response = await fetch("https://api.randomuser.me/?nat=US&results=10");
        let { results } = await response.json(); // 객체의 구조분해할당
        console.log(results);
    }
    catch (err) {
        console.error(err);
    }
};

 


클래스

  • 이전방식
function Vacation(destination, length) {
	this.destination = destination
	this.length = length
}

Vacation.prototype.print = function() {
	console.log(this.destination + "는 " + this.length + "일 걸립니다.")
}

var trip = new Vacation("마우이", 7)
trip.print()

 

  • 클래스를 사용해 정의
    최신 자바스크립트에서는 클래스를 명시적으로 선언한다.

  • 상속
    클래스를 정의했다면, 상속 가능하다.

'React' 카테고리의 다른 글

JSX를 사용하는 리액트  (0) 2023.11.03
리액트의 작동 원리  (0) 2023.11.01
자바스크립트를 활용한 함수형 프로그래밍  (0) 2023.10.31
React를 위한 자바스크립트  (0) 2023.10.28
React 시작하기  (0) 2023.10.27