[우아한 테크러닝] 2일차) JavaScript & Redux

2020. 9. 4. 00:20React/우아한 테크러닝

우아한 테크러닝 2일차


자바스크립트 훑어보기
리덕스 간단하게 만들어보기

 

Javascript


 

function


js에서는 함수도 값으로 변수에 넣을 수 있다 -> 함수도 값이다
js의 함수는 반드시 값을 반환하게 되어 있음 => 명시적으로 return 쓸 때 / 리턴이 없으면 undefiend 리턴
new 연산자의 경우는 명시적으로 인스턴스 ({ }) 반환

 

// 함수 정의문
function foo() {
  return 0;
}


// 함수식 -> 이름 정해줘도 변수명을 함수 이름으로 하기 때문에 익명함수 사용가능
// 함수를 값으로 취급할 때만 함수 이름 생략가능

const bar = function () {
  return 2;
}

// 최초에 1번만 실행되어야 하는 코드들일 경우
// 즉시 실행 코드 => 익명 함수는 이렇게 사용

(function(){
  return 1;
})();

bar();

 

// 함수 정의문
// 함수를 인자로 받아서 함수 리턴하는 함수 -> 일급함수 / high order function

function foo(x)  {
  x();
  return function(){
  };
}


// 인자로 함수를 전달하는 것: 콜백 함수

const y = foo(function(){
  console.log('aaaaaa')
});

 

react에서 high order component
컴포넌트를 인자로 받아서 쪼금 달라진 컴포넌트를 뱉는 함수들

함수는 코드를 묶고있는 값이라 생각하면 쉬움
값인데 그 안에 코드들이 묶여있고 그걸 실행(호출) 시키면 값을 얻음
함수를 리턴하는 애들 -> 바로 값을 뱉을 수는 없지만 값을 얻기 위한 코드를 줄 수 있다

 

 

재귀호출

const foo = function foo(){
  foo();
  // 재귀호출 시에는 자기 이름이 있어야 호출 가능함
  // 무조건 함수이름 생략하는 것은 아니다
}

 

 

화살표 함수

const foo = function (x){
  (...)
}  

// 화살표 함수
// function이 화살표로 바뀌었다
// 한줄함수 , 람다식이라고도 부름

const bar = (x) => {
	return x * 2;
}


console.log(bar(10));  // 결과값을 뱉어


const x = 10;
const y = () => 10;
console.log(x, y());

// x는 값이기 때문에 계산 X => 더 쪼갤 수 없는 값: primitive type
// y에는 계산 가능

// js 모든 코드는 식과 문으로 나눌 수 있음
// 실행의 결과가 값으로 마무리되면 식 => 세미콜론으로 마무리가 됨
// ex) 1+10; / foo(); / 1 + 10 + foo();
// 삼항연산자는 연산자, 결과는 값이 나오니까 식
// 실행의 결과가 값이 아닌 것 => 세미콜론이 없는 애들
// ex) if(switch) => conditional 문 / while(do-while, for..) -> 반복문
// 반복문: 단 하나의 반복문만 알고 있으면 모든 반복문 로직을 다 쓸 수 있대
// 반복 속도는 다 같다

 

 

new 연산자

// 동적 바인딩
const x = {};
x.name = 10;

// 객체 리터럴
const y = {
  z: 10
}

function foo() {
  this.name = 10;
}

const a = new foo();  // 인스턴스 객체


if (a instanceof foo) {
	// foo 함수가 만든 객체인지 확인할 수 있음
	// 일종의 위임 => 객체 내부의 형태를 확인하는 위임, 어떤 함수가 만들었는지 간이로 검사
}

console.log(a);

// new 연산자 호출되면
// 빈 객체 만들고 (this)
// this 이용해서 동적 바인딩
// 새로운 객체를 찍어낸다 => 그래서 생성자

 

 

class

function Foo()  {
  this.name = 10;
}


// 생성자 함수는 암묵적으로 constructure / prototype 등이 숨겨져 있음
// class는 컨스트럭터 => 객체를 찍어내는 애가 명확하게 드러나 있다
// 생성자 함수는 new 있어도 호출되고 없어도 호출됨
// class로 만들면 new로 호출하지 않으면 호출되지 않음

class Bar {
  constructor() {
    this.name = 10;
  }
}


console.log(Foo());
console.log(new Bar());

 

 

this와 클로저


this

// this
// 또 쓰로틀링, 디바운스 등에서 사용...

const person = {
  name: '구구',
  getName() {
    return  this.name; //this는 person => 이런걸 실행 컨텍스트라고 합니다
  }
}


console.log(person.getName());
// this는 실행하는 맥락상 소유자! getName이 실행하는 순간 소유자를 확인한다
// 호출하는 순간의 소유자와 연결
// 이게 실행 컨텍스트라고 합니다


// this가 결정되는 방식 -> 소유자가 사라지는 순간들이 있어요
const man = person.getName;
console.log(man());  // 에러가 나요!
// this가 딴놈이 되는 것 -> 실행하는 순간 호출자가 확인이 안된다!
// 호출자가 확인이 안되면 전역 객체에 연결이 된다!!!! (그래서 window 객체)


// 이벤트 시에! -> 콜백
button.addEventListener('click', person.getName);  // 소유자가 벗겨져요


// 항상 this가 뭔지 확인해야 합니다
// this는 왜 이렇게 만들어졌니?
// this를 이래저래 바꿔서 만들어봐라..
// 근데 이걸 리앸 앵귤러 만들거야? 아니면 잘안쓴다


button.addEventListener('click', person.getName.bind(person));
// 그래서 this 고정을 해준다


// 클래스 안에서는 this가 고정이 됩니다

 

 

closure

// closure

function  foo  (x)  {
  return  function  bar()  {
    return  x;
  }
}

const f = foo(10);  // f에는 bar가 옵니다
console.log(f());

// 함수가 호출되면 scope가 생깁니다
// 함수 묶고 있는 {} 기준으로 생김 -> es6에서

// 클로저: 자기 스코프 체인 바깥쪽에 있는 변수라면 그걸 함께 들고 있어요
// foo가 호출된다면 foo의 스코프는 사라지지만
// 변수 x는 클로저 영역에 저장이 되어 있기 때문에 다시 접근 가능
// 값을 보호할 때 많이 사용

// 클로저는 커링에 사용 const sum = a => b => a + b

 

 

모듈 패턴

// 모듈패턴

const person = {
  age:  10
}


person.age = 500;  // 이런 거를 막고 싶다 근데 방법이 없다


// 그걸 막으려고 이렇게 썼어

function makePerson() {
  let age = 10;
    return {
      getAge(){
        return age;
      },
      setAge(x) {
        age = x >  1  && x <  130  ? x : age;
      }
   }
}


let  p  =  makePerson();
console.log(p.getAge());  // getAge만이 age에 접근 가능해서 age를 보호 가능

 

 

비동기


callback

// callback

setTimeout(function (x) {
  console.log("앗싸");
  setTimeout(function (y) {
    console.log("웃싸");
  }, 2000);
}, 1000);

// depth가 깊어지면 callback hell
// 보기안좋고 에러나면 에러 엌케찾고 에러처리 엌케하고...

 

 

promise

// promise

// 새로운 프로미스 인스턴스를 만듭니다
const p1 = new Promise((res, rej) => {
// resolve: 확정되었다 -> 성공 then에 입력된 애들 실행시켜줘
// reject: 거부되었따 -> 실패 catch에 입력된 애들 실행시켜줘

// resolve, reject도 closure 영역에 잡혀서 함꼐 넘어가고 있따

  setTimeout(()  =>  {
    res("응답1");
  },  1000);
});


const p2 = new Promise((res, rej) => {
  setTimeout(()  =>  {
    res("응답2");
  },  1000);
});


// 내장 then이 있어서 thenable 객체라고도 함

p1
 .then(p2)
 .then(function  (r)  {
	// 응답을 받을 함수
	// 누가 호출을 하나? promise의 인자로 있는 저 함수들
	console.log(r);
	})
	.catch(function  (e)  {
	  console.log(e);
	});

// 이거가 체이닝

 

 

async / await

// async / await

// promise 객체를 리턴하는 delay 함수
// res를 사용하지 않으면 영원히 pending 상태로 남게 됩니다

const delay = (ms) => new Promise((res) => setTimeout(res, ms));


// main 함수는 비동기 함수이다

async function main() {
  console.log("1");
  try {
    await delay(2000);
      // async 내부에서 쓸 수 있어요
      // thenable 객체가 있을 때 resolve 함수가 반환하는 값을 리턴값으로 넘겨주는 것처럼 행동
      // 실제로 비동기를 쓰면서 동기적으로 보이게 작동: background는 promise
      
      console.log("2");
  } catch (e) {
	// reject는 이 안에 잡힙니다
    console.error(e);
  }
}


main();

 

 

커링
인자 여러개 있을때 인자당 함수 하나씩 쪼개서 사용하는 방식

function foo(a, b, c) {
 (...)
}

// 위와 같은 함수를 아래처럼 커링을 사용해서 다시 쓸 수 있습니다

function foo(a) {
  return function(b) {
    return function(c) {
      return a + b + c;
    }
  }
}

const foo = a => b => c => a + b + c;

 

 

Redux


 

리덕스 아키텍쳐 (flux)


 

Action -> dispatcher -> store -> view

 

 

만들어 봅시다!