221011 TIL - 구조분해할당

김민승·2022년 10월 11일
1

TIL

목록 보기
20/24
post-thumbnail

반복문 구조분해할당

객체와 배열은 자바스크립트에서 가장 많이 쓰이는 자료 구조입니다.

키를 가진 데이터 여러 개를 하나의 엔티티에 저장할 땐 객체를,
컬렉션에 데이터를 순서대로 저장할 땐 배열을 사용하죠.

개발을 하다 보면 함수에 객체나 배열을 전달해야 하는 경우가 생기곤 합니다. 가끔은 객체나 배열에 저장된 데이터 전체가 아닌 일부만 필요한 경우가 생기기도 하죠.

이럴 때 객체나 배열을 변수로 '분해’할 수 있게 해주는 특별한 문법인 구조 분해 할당(destructuring assignment) 을 사용할 수 있습니다. 이 외에도 함수의 매개변수가 많거나 매개변수 기본값이 필요한 경우 등에서 구조 분해(destructuring)는 그 진가를 발휘합니다.

출처: 모던자바스크립트 튜토리얼- 구조분해할당

of로 순회를 돌아야 key와 value를 한꺼번에 출력할 수 있는데, 위에서는 of로 순회가 불가능함.

이렇게 하면 for of문 사용가능

일반 변수 선언의 구조분해할당 예시

// 이름과 성을 요소로 가진 배열
let arr = ["rosy", "kim"]

// 구조 분해 할당을 이용해
// firstName엔 arr[0]을
// surname엔 arr[1]을 할당하였습니다.

let [firstName, surname] = arr;

alert(firstName); // rosy
alert(surname);  // kim

이제 인덱스를 이용해서 배열에 접근하지 않고도 변수로 이름과 성을 사용할 수 있게 되었다.
split 같은 반환 값이 배열인 메서드 함께 이용해도 좋다.


let a, b, c
[a, b] = [10, 20]

let one, two, three
[one, two, three] = '010-0000-0000'.split('-')
// ['010','0000','0000']

let one1, two1, three1, four1
[one1, two1, three1, four1] = '010-0000-0000'.split('-')
// ['010', '0000', '0000']

[one1, two1, three1, ...four1] = '010-0000-0000-01-02-03'.split('-')
// ['010', '0000', '0000', '01', '02', '03']
console.log(four1)
//['01','02','03']

// 쉼표 사용하여 요소 무시
// 두 번째 요소는 필요하지 않음
let [firstName, , title] = ["민승", "희수", "유정", "도영"];
console.log( title ); // 유정

구조분해할당의 여러 예시들.
아래 문제를 풀어보자~

// 구조분해할당 문제입니다.
data = [10, 20, 30, 40, 50]

// 문제 1 
// a, b, c로 각각을 분해할 것입니다.
// a에는 10, b에는 20, 30, 40, c에는 50을 할당해보세요.

//문제 1 답
[a, b, c] = [data[0], [data[1], data[2], data[3]], data[4]]; 

// 문제 2
// a, b, c로 각각을 분해할 것입니다.
// a에는 10, 20, 30, b에는 40, c에는 50을 할당해보세요.

//문제 2 답
[a, b, c] = [[data[0], data[1], data[2]], data[3], data[4]];

// 문제 3 (정상 작동. 마지막에만 사용할 수 있음)
// a, b, c로 각각을 분해할 것입니다.
// a에는 10, b에는 20 c에는 30, 40, 50을 할당해보세요.

///문제 3 답
[a, b, ...c] = [10, 20, 30, 40, 50]
/// ...로 나머지 요소 가져올 수 있음. 

Object 구조분해할당

구조분해할당으로 객체도 분해할 수 있다.

let {var1, var2} = {var1:, var2:}
// 우측에 분해하고 싶은 객체를, 좌측엔 객체 프로퍼티의 패턴을 넣기

// 추가 예시 보자
let options = {
  title: "Menu",
  width: 100,
  height: 200
};

let {title, width, height} = options;

console.log(title);  // Menu
console.log(width);  // 100
console.log(height); // 200

// 순서는 중요하지 않다. let {...} 안의 순서가 바뀌어도 동일하게 동작함
let {height, width, title} = { title: "Menu", height: 200, width: 100 }

할당 연산자 좌측에는 조금 더 복잡한 패턴이 올 수도 있다.
options.width를 w라는 변수에 저장해보자! 좌측 패턴의 콜론(:) 사용하기

let options = {
  title: "Menu",
  width: 100,
  height: 200
};

// { 객체 프로퍼티: 목표 변수 }
let {width: w, height: h, title} = options;

// width -> w
// height -> h
// title -> title

alert(title);  // Menu
alert(w);      // 100
alert(h);      // 200

배열 혹은 함수의 매개변수에서 했던 것 처럼, 객체에도 표현식이나 함수 호출을 기본값으로 할당할 수 있다. 물론 표현식이나 함수는 값이 제공되지 않았을 때 평가 혹은 실행됨.

let options = {
  title: "Menu"
};

let {width = prompt("width?"), title = prompt("title?")} = options;

alert(title);  // Menu
alert(width);  // prompt 창에 입력한 값
// 위 예시를 사용하면 width 값만 물어보고 title 값은 물어보지 않습니다.

배열 디스트럭팅

전개구문 사용법


함수

함수의 구조

파라미터가 선언될때 아규먼트가 실행된다
함수 내부에 있는 함수가 파라미터

파라미터, 아규먼트

Parameter -> 매개변수
Argument -> 전달인자,인자

function 함수이름(파라미터){
	console.log(파라미터)
    console.log('hello world')
    return 100
}

let 아규먼트 = 1000
함수이름(아규먼트)
// 내가 파라미터에 전달해 주는것이 아규먼트

// 1000
// hello world
// 100
// 함수의 구조. 함수 이름만 읽고 함수가 실행되는건 나중임
  • return의 용도 (함수 종료, 반환값)
    두가지는 꼭 알아두기

return은 자기가있던 자리에 어떤 값을 줄지
console.log도 함수임. 반환값 + undifined

지역변수 전역변수

let z = 100; // 전역변수
function sum(x){
	//x는 parameter 면서 지역변수(local val)
    let y =50; //y는 지역변수
    z= z + y;
    return x + y;
}

=>두가지를 잘 구별해야함

function 안녕(){
    console.log('hello')
    console.log('hello')
    console.log('hello')
    if (특정조건){
        return 100
    }
    else {
        console.log('hello')
        console.log('hello')
        console.log('hello')
        return 1000
    }
    // return 아래 코드는 실행하지 않습니다.

함수를 사용하는 이유

  1. 재사용성
    얼마든지 어디서든지 사용 가능함
    재사용하지 않을 코드는 함수로 정의하나? => 가능하면 함수로 그래도 만들라

  2. 유지보수
    3번사항 + 변수의 스코프 제한

  3. 구조파악이 용이하다

  4. (참고만)추상화로 개발하는 것이 객체지향 프로그래밍 언어의 언어 철학에 맞다

함수의 다양한 형태

function 함수1 (a, b, c){
    return a + b + c
}

// 콘솔창의 기능이에요. 마지막 라인에 한하여 console.log()를 찍지 않아도 return값을 console창에 출력해줍니다.
함수1(10, 20, 30) 
함수1(10, 20, 50)

// 다음 실행 값은?
console.log(함수1(10, 20, 30))
console.log(함수1(10, 20, 50))

// 필요 이상의 아규먼트를 넣었을 때
함수1(10, 20, 30, 40) // Error를 뿜지 않습니다. 60

// 필요 이하의 아규먼트를 넣었을 때
함수1(10, 20)
/*
function 함수1 (a, b, c){
    return a + b + String(c)
}
함수1(10, 20) // '30undefined'
*/

구조분해할당을 이용한 아규먼트 처리

함수2('hello', 'world', 10, 20, 30, 40)

function 함수2(a,b,...c){
	return Math.max(...c)
}
//40. c가 나머지 요소 전부 다 받아서 처리할 수 있다

기본값 할당

function 함수3(a=10, b=20, c=30){
    return a + b + c
}

console.log(함수3()) // 60
console.log(함수3(100)) // 150
console.log(함수3(100, 200)) //330
console.log(함수3(100, 200, 300)) //600

console.log(함수3(c=1000)) // 1030이 되어야 하는거 아니에요? => 순서대로 들어감!!!!! 저건 기본값일뿐.
// 1050

console.log(함수3(c=1000, a=2000)) 
// 3030

초깃값 설정

얘는 그냥 스킵

재귀함수

함수에서 자기 자신을 호출하는 함수
재귀함수는 주로 반복문을 구현할때 사용한다.

재귀함수의 가장 대표적인 사용 예제는

팩토리얼(factorial)

function factorial(n){
    if (n <= 1){ // 종료 조건이 없으면 무한반복이 된다.
        return 1
    }
    return n * factorial(n - 1)
}

factorial(5)

let result = 1;
for (let i = 2; i < 6; i++) {
    result *= i
}
console.log(result)
//팩토리얼 함수 뜯어보기
                n       n <= 1      return
factorial(5)    5       false       5 * factorial(4) = 120
factorial(4)    4       false       4 * factorial(3) = 24
factorial(3)    3       false       3 * factorial(2) = 6
factorial(2)    2       false       2 * factorial(1) = 2
factorial(1)    1       true        1

재귀함수로 문자열 뒤집기

function reverse(txt){
    if (txt.length <= 1) {
        return txt
    }
    return reverse(txt.slice(1)) + txt[0]
}
reverse('hello world');

/*
참고사항
'hello'.slice(1)
'ello'
n                   txt.length <= 1         return
reverse('hello')    false                   reverse(txt.slice(1)) + 'h' = 'olleh'
reverse('ello')     false                   reverse(txt.slice(1)) + 'e' = 'olle'               
reverse('llo')      false                   reverse(txt.slice(1)) + 'l' = 'oll'            
reverse('lo')       false                   reverse(txt.slice(1)) + 'l' = 'ol'                      
reverse('o')        true                    'o'                      
*/

화살표함수

function 함수(x,y){
	return x+y
}

function 함수2(x,y) => x+y

function 함수2(x,y){
  	let z= x+y
	return x+y
}

let 함수2 = (x,y) => {let z =x+y
return z}

호이스팅

변수가 끌어올려지는 현상
최상위로 끌어올려짐.
선언은 호이스팅 되지만 할당은 호이스팅 되지 않는다

중간고사 점수 구하는 함수

const getAverage = (data) => {
  let 중간고사점수 = data.map(i => i.중간고사점수)
  let 중간고사점수합 = 중간고사점수.reduce((acc, cur) => acc+cur) 
  return 중간고사점수합 / data.length;
}

function 평균구하기(data){
    let score = data.map((i)=>i.중간고사점수);
    let sum = score.reduce((현재값,누적값)=>(현재값+누적값),0);
    return sum / data.length;
}

call by value, reference, sharing

클로저

폐쇠된 공간(함수)안에 데이터에 접근하기 위한 테크닉
함수 실행 시 클로저에 저장된 x,y 값에 접근하여 값을 계산
지역스코프에서 값을 찾고, 없으면 그 밖에 있는 스코프에서 찾고, 계속해서 찾아 올라가 전역 스코프까지 찾아보는것을 스코프체이닝
=> 어려운 얘기로는 내부 렉시컬 환경에서 찾고, 없으면 전역 렉시컬 환경에서 찾는다.

클로저 예제

profile
꾸준함을 이길 방법은 없다

2개의 댓글

comment-user-thumbnail
2022년 10월 11일

암튼 중요하다 네 알겠습니다..

1개의 답글