출처: https://bumcrush.tistory.com/182 [맑음때때로 여름]

상세 컨텐츠

본문 제목

Week1(Javascript)

MOFE 스터디

by 장동균 2020. 9. 15. 01:40

본문

첫 1주는 Javascript에 집중한다. JS를 제대로 모르고 상태로 react와 node를 공부해봐야 기술부채만 쌓여간다. 항상 기본이 중요하다. 이 1주동안 javascript.info page와 러닝 자바스크립트 책을 정독하며 내가 몰랐던 부분과 중요하다고 생각이 드는 부분들을 이곳에 정리한다.     (#FFFF00 형광색 색상 코드!!!)


1. Javascript에서 함수는 반드시 return 값을 가져야 한다.

  • return을 쓰면 명시적으로 그 값을 반환
  • return을 쓰지 않는 다면 undefined가 반환(undefined 또한 하나의 값이다!)
  • 함수 내부의 구문이 1줄일 경우 계산 후 결과값을 바로 return 하기 때문에 return 문을 쓰지 않아도 되지만 여러줄이면서 return해야 하는 특정한 값이 있다면 return을 명시해야 한다. (이 마지막은 arrow function에서만 가능한 기능인듯)

2. 함수의 naming을 할 때는 동사를 접두어로 붙여 함수를 만드는 것이 관습이다.

 

  • "get…" – 값을 반환함
  • "calc…" – 무언가를 계산함
  • "create…" – 무언가를 생성함
  • "check…" – 무언가를 확인하고 불린값을 반환함
  • "show..." - 무언가를 보여줌

ex) showMessage(), getAge(), calcSum(),  createForm(), ...

 

함수의 이름을 지을 때 함수 이름에 언급되어 있는 동작들만을 정확히 수행하여야 한다. 그 이외의 동작을 수행한다면 naming을 사실상 할 이유가 없다.

 

  • getAge 함수는 나이를 얻어오는 동작만 수행해야 합니다. alert 창에 나이를 출력해주는 동작은 이 함수에 들어가지 않는 것이 좋습니다.
  • createForm 함수는 form을 만들고 이를 반환하는 동작만 해야 합니다. form을 문서에 추가하는 동작이 해당 함수에 들어가 있으면 좋지 않습니다.
  • checkPermission 함수는 승인 여부를 확인하고 그 결과를 반환하는 동작만 해야 합니다. 승인 여부를 보여주는 메시지를 띄우는 동작이 들어가 있으면 좋지 않습니다.

project에서 naming만 잘해도 architecture의 절반 이상을 먹고 들어간다고 한다. 다른 것들도 연습해서 100%가 된다면 좋겠지만 항상 가장 기본적인 것이 가장 중요하다. 변수 하나, 함수 하나의 이름을 짤 때에도 이 이름을 보고 바로 이 변수 혹은 함수가 하는 일을 예측할 수 있게 만드는 naming sense를 갖추는 것이 중요하다.


3. 함수 표현식 vs 함수 선언문

 

//함수 선언문
function foo(a, b) {
	return a + b;
}
//함수 표현식
let foo = function(a, b) {
	return a + b;
};

먼저, 식과 문을 구문하는 가장 큰 외관상의 차이는 semi column(;)의 유무 이다. 식의 마무리는 반드시 semi column인 반면 문의 마무리에서는 semi column을 사용하지 않는다.(문은 대표적으로 if문, while문 같은 것들이 있을 수 있다.)

 

내부적으로는, 함수 표현식은 실제 흐름이 해당 함수에 도달했을 때 함수를 생성하는 반면, 함수 선언문은 함수 선언문이 정의되기도 전에 호출이 가능하다.

 

함수 표현식에서의 함수 생성 시기는 상식적으로 당연한 반면, 함수 선언문에서의 함수 생성 시기는 상식 밖이다.

이것이 가능한 이유는 자바스크립트 내부 알고리즘에 의해 스크립트를 실행하기 전, 준비단계에서 전역에 선언된 함수 선언문들을 찾고, 해당 함수들을 생성하기 때문이다. 즉, 스크립트가 진짜 실행되기 전 초기화 단계에서 함수 선언 방식으로 정의한 함수가 생성되는 것이다.

 

//javascript.info에 있는 예제

sayHi("John"); // Hello, John

function sayHi(name) {
  alert( `Hello, ${name}` );
}
sayHi("John"); // error!

let sayHi = function(name) {  // (*) 마술은 일어나지 않습니다.
  alert( `Hello, ${name}` );
};

그 다음으로 볼 차이점은, scope이다.

 

함수 선언문이 코드 블록 내에 위치하면 해당 함수는 블록 내 어디서든 접근할 수 있다. 하지만, 블록 밖에서는 함수에 접근하지 못한다.

 

반면에 표현식에서는 블록 밖에서도 블록 내부에 존재하는 함수 속의 함수, 객체, 변수 모두에 접근이 가능하다. 이것을 클로저(closure)라고 한다.

(함수가 특정 스코프에 접근할 수 있도록 의도적으로 그 스코프에서 정의하는 경우를 클로저라 한다.)

 

(러닝 자바스크립트 p.196)

let globalFunc;
{
  let blockVar='a';
  globalFunc=function(){
    console.log(blockVar);
  }
}
globalFunc();    //'a'

globalFunc는 블록 안에서 할당을 받았기 때문에, 이 블로 스코프와 부모인 전역 스코프가 하나의 클로저를 생성한다. 이 클로저 덕분에 어디서든 블록 스코프 내부의 식별자에 접근이 가능해진다.

 

스코프의 범위를 유지하고 싶을 때 이 클로저 개념과 즉시실행함수를 함께 이용한다.(ES6에서 블록 스코프 변수를 도입하면서 즉시 실행 함수의 사용 빈도가 엄청나게 떨어지긴 했다.)

 

wookgu.tistory.com/7

 

클로저(closure)와 즉시실행함수(IIFE)

Node.js를 이용해 웹사이트를 만들어보긴 했지만 자바스크립트에 대해 제대로 알고있지 않은 것 같아 최근에 O'REILLY에서 나온 '러닝 자바스크립트' 책을 보면서 공부를 시작했다. 클로저라는 말에

wookgu.tistory.com

이곳에 이 둘을 함께 사용하는 예제가 되게 잘 설명 되어 있어서 참고하면 좋을 것 같다.

 

스코프와 실행컨텍스트

poiemaweb.com/js-execution-context

 

Execution Context | PoiemaWeb

Execution Context(실행 컨텍스트)는 scope, hoisting, this, function, closure 등의 동작원리를 담고 있는 자바스크립트의 핵심원리이다. 실행 컨텍스트를 바로 이해하지 못하면 코드 독해가 어려워지며 디버��

poiemaweb.com

 

모던자바스크립트에 따르면 함수 표현식 보다는 함수 선언문을 먼저 고려하는 것이 좋다고 말한다. 

항상 리액트의 component와 그 속의 함수들을 정의할 때 함수 선언문으로 해야할까 아니면 arrow function을 이용한 함수 표현식으로 해야 할까 고민하곤 했었다. 

최근에 velopert님의 블로그에서 함수 선언문으로 component를 작성하는 것이 아주 조금의 성능적 이점을 갖는다는 내용을 본 이후로는 항상 선언문으로 작성하려 노력했다. 나에게 있어서 이 글은 더더욱 함수 선언문을 사용하여야 하는 계기가 되었다. 특별한 이유가 없다면 항상 함수는 선언문으로 작성하던 노력을 이어가야겠다. 


3. 함수의 호출과 참조

 

getGreeting(); // "Hello, World!"

getGreeting; // function getGreeting()

 

위에는 함수 호출, 아래는 함수 참조(reference)이다.

 

함수를 호출하지 않고 참조할 수 있다는 특징은 자바스크립트를 굉장히 유연한 언어로 만들어준다.

 

const f = getGreeting;

f();                  // "Hello, World!"   와 같은 실행이 가능하다.

 

react에서도 이런 기능이 유용하게 쓰이는데

 

onClick={onClick}             //위에 onClick function을 정의해놨다고 가정.

 

와 같이 자주 쓰인다. 저번에 리액트 공부를 할 때 이 함수의 호출과 참조를 모르고 onClick={onClick} 이런 식으로 구현하니까 아무 생각없이 onClick={onClick(paremater)} 이런 식으로 구현해버린 적이 있다. 이렇게 하면 함수 참조가 아닌 호출이기 때문에  rendering process에서 지 혼자 실행돼버리고, 이 버튼은 더이상 동작하지 않게 된다. parameter가 없는 경우 저런식으로 함수 참조 기능을 이용해 간단히 적을 수 있지만 parameter가 있는 경우

onClick={()=>onClick(parameter)} 이런 식으로 만들어 click event가 발생했을 때 onClick function이 작동하도록 만들어야 한다.

 


4. this 키워드와 apply, call, bind

 

velog.io/@josworks27/%ED%95%A8%EC%88%98%ED%98%B8%EC%B6%9C-call-apply-bind-%EC%B0%A8%EC%9D%B4

 

함수 호출 call, apply, bind의 차이

함수 호출과 관련하여 지금까지 자주 쓰이지는 않았지만, 반드시 알아야 할 개념이 있다. 바로 call / apply / bind을 이용한 함수 호출 방법이다.자바스크립트에서 함수를 호출하는 방법에는 먼저, �

velog.io

예제 코드는 일단 이곳에 있는 코드를 보면 좋을 것 같다.

 

먼저, 까다로운 this에 대해 알아야 한다. (예제 출처 - 러닝 자바스크립트 p.177)

const o = {
    name: 'Wallace',
    speak() {return `My name is ${this.name}!`},
}

o.speak();

o.speak()를 실행하면 우리가 원했던 결과인 My name is Wallace가 나온다. 여기서 this 값이 o에 묶인 이유는 o에서 speak를 호출 했기 때문이다.

 

const speak = o.speak;
speak === o.speak; //true
speak(); 

speak()의 결과는 My name is undefined 이다. this가 어디에 속하는 지 알 수 없기 때문에 이런 결과가 나온다. 

 

이를 해결하기 위해서 객체 속에 변수를 만들고 이 변수에 this를 할당한다. 하지만, 이는 굉장히 까다로운 일이기 때문에 이를 해결하기 위해 apply, call, bind 같은 함수들을 사용한다.(러닝 자바스크립트 p.183부터) 하지만, 이 조차도 굉장히 까다로운 일이다. 일일이 bind를 적고 그 bind된 객체를 파악하고 있는 일은 결코 쉬운 일이 아니다.

 

이를 해결할 가장 좋은 방법은 arrow function이다. arrow function은 lexical context이다. (일반 함수는 Execution context) 일반 함수에서는 this의 값이 달라질 수 있기 때문에 반드시 bind해야 하지만 arrow function은 lexical context이기 때문에 bind하지 않아도 this 값이 변하지 않는다.

 

사실상 react hook을 쓰다보면 this를 사용할 일은 거의 없다. 하지만, 이 자바스크립트 개념은 굉장히 중요한 개념이기 때문에 면접에서도 나올 수 있는 개념이다. 잘 알고 있어야 한다.

 


5. Javascript의 garbage collector

 

자바스크립트에는 garbage collector가 존재한다. 이 garbage collector는 더 이상 쓸모가 없는 원시값, 객체, 함수 등을 자동으로 날려줘서 memory 공간을 확보한다. 따라서, 개발자가 직접 이 공간을 확보하기 위해 시간을 쓰지 않아도 된다.

 

ko.javascript.info/garbage-collection

 

가비지 컬렉션

 

ko.javascript.info

자바스크립트가 어떻게 공간을 확보하는지 잘 설명되어 있다. 그냥 가볍게만 읽어봐도 되지 않을까 싶다.

 

www.youtube.com/watch?v=vZRmCbl871I

 

garbage collector를 이해하기 좋은 영상이라 생각한다.


6. 배열 자체를 수정하는 배열 메서드와 새 배열을 반환하는 메서드 구분

 

리액트에서는 불변성 유지를 위해 반드시 새 배열을 반환하는 즉 side effect가 없는 method를 써야 한다.

 

배열 자체를 수정하는 메서드 => push, pop, shift(배열의 처음에 요소를 제거), unshift(배열의 처음에 요소를 추가), splice, fill, reverse

 

새 배열을 반환하는 메서드 => concat, slice(배열의 일부를 가져오는 slice method는 새 배열을 봔환하지는 않지만 기존 배열을 수정하지 않기 때문에 이곳에 넣었다. 기본적으로 side effect가 없기 때문에.), map, filter, reduce

 

새 배열을 반환하는 메서드들은 반드시 기억하고 활용해야 한다.

'MOFE 스터디' 카테고리의 다른 글

Week6(JavaScript)  (0) 2020.10.28
Week5(Javascript)  (0) 2020.10.17
Week4(Javascript)  (0) 2020.10.11
Week3(Javascript)  (0) 2020.10.02
Week2(Javascript)  (0) 2020.09.24

관련글 더보기

댓글 영역