
해당 게시글은 모던 리액트 딥다이브를 읽고, 작성한 정리글입니다.
// sum 은 함수명
// a,b는 매개변수
function sum(a, b) {
// return 으로 작성된건 반환값
return a + b
}
// 함수 호출과, 인수로 전달 되는 숫자들
sum(10, 24)
함수란,
작업을 수행하거나, 값을 계산하는 등의 과정 등을
하나의 블록 단위로 감싸서 실행 단위로 만들어 둔 것이다.
리액트 함수도 이와 같은 형태를 따른다.
// Component 라는 함수를 선언하며,
// props 라는 단일 객체를 받고,
function Component(props) {
// JSX 를 반환한다.
return <div>{props.hello}</div>
}
// 함수 선언문의 일반적인 형식
function sum(a, b) {
return a + b
}
함수 선언문은 표현식이 아닌 ❌, 일반문으로 분류된다.
(이때 표현식이란 값을 산출하는 구문을 의미, 위에선 어떠한 값도 표현되지 않았기에 포함이 안되는 것이다)
const sum = function sum(a, b) { return a + b}
하지만 다음과 같이 표현식으로도 사용될 수 있기도 하다.
자바스크립트에서 함수는 일급객체에 해당한다.
자 그렇다면 일급객체가 뭘까?
일급객체란?
다른 객체들에 일반적으로 적용가능한 연산(변수에 할당, 함수의 인자로 전달, 함수의 반환값으로 사용)을 모두 지원하는 객체
위에서 변수에 객체를 할당하는 형태가 바로, 함수 표현식이다.
보통, 위의 예제와 다르게 function 뒤에 할당하려는 함수의 이름을 생략하는 것이 일반적인데, 이는 실제 함수 호출을 위해 사용되지 않고 그저 식별자일뿐이기 때문이다.
그래서 둘이 뭐가 다를까요?
변수에 할당을 했는가(표현식), 아닌가 (선언식) 의 차이는
바로 호이스팅(hoisting)이다
(호이스팅이란: 변수와 함수의 선언이, 실행 전에 메모리에 등록되는 현상
코드 실행 전에 선언이 끌어올려진 것처럼 동작하는 자바스크립트의 특징)
함수선언식의 경우, 호이스팅으로 인해 선언 전에 호출하여도 정상적으로 작동한다.
하지만, 함수표현식의 경우, 특히 var에 할당했다면 undefined로 초기화되어 함수로서 호출이 불가능하기에 오류가 난다.
(let과 const는 TDZ로 인해 아예 접근이 불가하기에 오류가 난다. )
const add = new Function('a', ’b', 'return a + b')
add(10, 24)
위와 같이 생성자로 함수를 만들 수 있는데, 작성 관점에서 가독성이 떨어지기에 실제 많이 사용되지 않는다고 한다.
const add = (a, b) => {
return a + b
}
// const add = (a, b) => a + b
ES6에서 추가된 함수이다. 특징으로는
(1) constructor를 사용할 수 없고,
(2) 화살표 함수에는 arguments가 존재하지 않는다.
function hello() {
console.log(arguments)
}
// Arguments(3) [1, 2, 3, callee: f, Symbol(Symbol.iterator): f]
hello(1, 2, 3)
const hi = () => {
console.log(arguments)
}
// Uncaught ReferenceError: arguments is not defined
hi(1, 2, 3)
(3) 일반 함수와 화살표 함수는 this 바인딩에 있어서 차이를 보인다.
(this가 뭔데: 자신이 속한 객체나 자신이 생성할 인스턴스를 가리키는 값으로, 함수 호출 방식에 따라서 동적으로 결정된다 )
일반 함수의 경우, 호출된다면 그 내부의 this는 런타임 시점에서 결정되는 방식을 따르는데,
화살표 함수의 경우, 함수 자체의 바인딩을 따르지 않고 상위 스코프의 this를 그대로 따르게 된다. (선언 시점에서 this 결정 -> 상위 스코프로 )
그래서 단순 일반 함수를 축약한 형식이라고 보기엔 무리가 있다.
선언 방식 외에, 함수를 사용하는 방식에도 여러가지가 있다.
말 그대로 함수를 정의하고 그 순간 즉시 실행되는 함수인데,
단 한번만 호출되고, 다시금 호출할 수 없는 함수이다.
(function (a, b) {
return a + b
})(10, 24);
((a, b) => {
return a + b
},
)(10, 24) // 34
앞선 언급에서 자바스크립트의 함수가 일급 객체라는 특징으로, 함수를 인수로 받거나 결과로 새로운 함수를 반환할 수 있다고 말했다.
이런 역할을 하는 함수를 고차함수라고 하기도 한다.
// 함수를 매개변수로 받는 대표적인 고차 함수, Array.prototype.map
const doubledArray = [1, 2, 3].map((iem) => iem * 2)
doubledArray // [2, 4, 6]
// 함수를 반환하는 고차 함수
const add = function (a) {
return function (b) {
return a + b
}
}
add(1)(3)
1️⃣ 부수 효과를 최대한 억제하라
최대한 순수함수로 작동할 수 있도록 하되, 부수 효과를 피할 수 없다면useEffect와 같이 그 작동을 최소화 하는 것이 좋다
2️⃣ 가능한 한 함수를 작게 만들어라
명시적인 코드 라인수는 없겠지만, 최대한 하나의 책임을 맡게 하는 것이 좋다.
3️⃣ 누구나 이해할 수 있는 이름을 붙여라
네이밍은 최대한 간결하고 이해하기 쉽게 /useEffect나useCallback등 훅에 넘겨주는 콜백 함수에 네이밍 붙여주는 것도 가독성을 올리는 방법 중 하나
특정한 객체를 만들기 위한 일종의 템플릿
특히, 필요한 데이터나 이를 조작하는 코드를 추상화해 객체 생성을 더욱 편리하게 할 수 있다는 점에서 특징이다.
// 클래스를 상속 받을땐 extends를 사용한다.
// class Car extends vehicle {
class Car {
// constructor: 생성자다.
// 최초에 생성할 때 어떤 인수를 받을지 결정하며 객체를 초기화하는 용도로도 사용된다.
// (단, 단 하나만 존재할 수 있다, 혹은 필요없을 경우 생략도 가능하다)
constructor(name) {
// name은 프로퍼티로 인스턴스 생성시, 내부에서 정의할 수 있는 속성값이다.
this.name = name
}
// 인스턴스 메서드 : 실제 prototype에 선언되므로 프로토타입 메소드라고 불리기도 한다. (프로토타입이란 모든 인스턴스가 공유하는 객체)
honk() {
console.log('${thi .name}이 경적을 울립니다!')
}
// 정적 메서드 : 인스턴스가 아닌, 클래스 이름으로 호출할 수 있는 메서드
// 정적 메서드 내부의 this는 클래스 자기 자신을 가리킨다.
static hello() {
console.log('저는 자동차입니다')
}
// setter : 클래스 필드에 값을 할당할때 사용된다.
set age(value) {
this.carAge = value
}
// getter : 무언가 값을 가져올때 사용된다.
get age() {
return this.carAge
}
직접 객체에 선언하지 않았음에도, 프로토타입에 있는 메서드를 찾아 실행을 돕는 것을 프로토타입 체이닝이라고 한다.
모든 객체는 프로토타입을 갖는데, 특정 속성을 찾을때까지
자기 자신부터 -> (프로토타입을 타고) -> 최상위 객체인 Object 까지 훑는다.
(toString 메서드도 객체 어디에서도 선언하는 경우가 없지만, 프로토타입 체이닝을 거쳐 Object에 있는 toString을 찾아간다. )
클래스는 ES6부터 도입된 개념인데, 이전에는 프로토타입을 통해 클래스의 작동 방식을 유사하게 구현했다.
만일 ES6 미만의 환경에서는, _createClass 라는 헬퍼 함수를 만들어 클래스와 동일하게 동작할 수 있도록 변경한다.
클래스 작동을 생성자 함수로 매우 유사하게 재현할 수 있는데, 이처럼 클래스는 자바스크립트의 문법적 설탕 역할을 한다고 볼 수 있으며, 프로토타입을 기반으로 작동한다는 사실도 확인 할 수 있다.