모던 자바스크립트 Deep Dive 글 목록(스터디)
https://hello-kk.tistory.com/780
★책을 읽고 재점검해볼 내용★
함수는 호출 가능한 객체
함수 리터럴 의미
함수 표현식==함수 리터럴 표현식
매개변수, 인자, 인수 구분하기
순수함수 비순수함수(구분되는 기준이 다른 듯 함)
일급 객체의 의미
함수 리터럴 표현식과 함수 선언문의 함수 객체 생성 시점 차이
Rest 파라미터와 arguments 객체 비교
12.1 함수란?
함수 정의
함수 호출
12.2 함수를 사용하는 이유
코드 재사용, 유지보수의 편의성, 코드의 신뢰성
=> 추후 테스트 코드 작성 unit test
12.3 함수 리터럴
★함수 리터럴이 많이 등장한다. 의미를 숙지하기★
함수는 객체 타입의 값이다?!
=> Function 객체의 인스턴스. 속성으로는 함수의 이름, 매개변수, 내부코드, 반환값을 갖는다.
따라서 식별자(이름)을 붙일 수 있다.
객체는
변수에 할당하거나, 다른 객체의 속성으로 할당하거나, 함수의 매개변수로 전달하거나, 함수의 반환값으로 사용가능
함수도
변수에 할당하거나, 다른 함수의 매개변수로 전달하거나, 함수의 반환값으로 사용 가능
함수는 호출 가능한 객체의 한 종류. () 호출 연산자 사용하여 호출
함수 리터럴의 구성요소 => function 키워드, 함수 이름, 매개변수 목록, 함수 몸체
12.4 함수 정의
정의된 함수는 자바스크립트 엔진에 의해 평가되어 함수 객체가 된다.
함수를 정의하는 방법
(1) 함수 선언문
(2) 함수 표현식
(3) Function 생성자 함수
(4) 화살표 함수
6.5절을 참고해보자. 아래는 찾아본 내용이라 의미하는 바가 다를 수 있다.
선언declaration과 정의definition 의 차이
: 선언은 컴파일러가 해당 변수의 이름을 기억하는 것(선언만 하면 어떤 값도 할당되지 않는다. 이후 코드에서 사용하려면 값이 할당되어야 함)
정의는 변수에 값을 할당하여 메모리에 할당된 영역을 생성하는 것(변수에 할당된 값 사용 가능)
var k; //변수 k 선언
k = 'hello' //변수 k에 값 할당
12.4.1 함수 선언문
함수 리터럴과 동일하다. 하지만 함수 선언문은 이름을 생략할 수 없다.
function 함수명(매개변수1,매개변수2, ... ){
...
return ...
}
함수 리터럴에서 이름을 생략하면 익명함수=> 표현식, 콜백함수, 즉시실행 함수
함수 선언문은 표현식이 아닌 문이어서 변수에 할당할 수 없지만, 할당되는 것처럼 보이는 경우
함수 리터럴을 해석하는 방식의 차이
(1) 표현식이 아닌 문인 함수 선언문으로 해석
(2) 표현식인 문인 함수 리터럴 표현식으로 해석=> 함수 리터럴이 값으로 평가되는 문맥에서.
(2번 예시) 함수 리터럴을 변수에 할당하거나 피연산자로 사용하는 경우
함수 선언문은 리터럴과 형태가 동일=> 기명 함수 리터럴은 함수 선언문 또는 함수 리터럴 표현식으로 해석될 가능성이 있다
함수 리터럴을 피연산자로 사용한다는 것?
함수를 변수에 할당하거나, 다른 함수에 인수로 전달하거나, 반환값으로 사용하는 등의 경우.
=> 책에서의 예시는 그룹연산자 소괄호내에 있는 함수 리터럴은 리터럴 표현식으로 해석된다고 설명함(선언문으로 해석 안됨)
함수 리터럴 표현식=> 함수 이름은 몸체 내에서만 참조할 수 있는 식별자. 따라서 외부에서 함수를 호출할 수 없다. 함수를 가리키는 식별자가 없다.
함수 선언문 => 자바스크립트 엔진은 함수 선언문을 해석해 함수 이름과 동일한 이름의 식별자를 암묵적으로 생성하고, 함수 객체를 할당
=> 함수 이름으로 호출하는 것이 아니라 함수 객체를 가리키는 식별자로 호출
즉, 선언문을 함수 표현식으로 변환해 함수 객체를 생성하는 것과 비슷하다.
const hello = function hello(x){
return x
}
console.log(hello('k'))
12.4.2 함수 표현식
일급 객체: 값의 성질을 갖는 객체
함수 선언문: 표현식이 아닌 문
함수 표현식: 표현식인 문
왜 선언식이 기준이 아닌걸까?
함수 선언문은 함수 리터럴을 사용하지만, 리터럴과 선언문이 결합된 형태로 작성되어 있기 때문에 함수 리터럴 선언문이라고 부르지 않습니다. 함수 선언문은 자바스크립트 엔진이 스크립트를 실행하는 과정에서 먼저 함수를 선언하고, 그 후 코드를 실행하는 것을 의미합니다. 이에 반해 함수 리터럴은 변수에 할당된 후, 그 변수를 통해 함수를 호출하는 방식으로 사용됩니다. |
12.4.3 함수 생성 시점과 함수 호이스팅
선언문과 표현식은 생성 시점에 차이가 있음
선언문: 선언문 이전에 호출 가능
표현식: 표현식 이전에 호출할 수 없다
(1) 자바스크립트 엔진 실행
(2) (함수 선언문의 경우) 함수 객체가 생성
(3) 자바스크립트 엔진은 함수 이름과 동일한 이름의 식별자를 암묵적으로 생성
(4) 생성된 함수 객체를 식별자에 할당 => 식별자는 함수 객체로 초기화
(5) 런타임 실행
정리하면, 런타임 이전에 자바스크립트 엔진이 실행된다. 함수 선언문 이전에 호출시 함수 호이스팅에 의해 호출가능
함수 표현식은 변수에 할당되는 값이 함수 리터럴인 문.
변수 선언은 런타임 이전에 실행되어 undefined로 초기화
변수 할당문의 값은 할당문이 실행되는 시점인 런타임에 평가된다
따라서, 함수 표현식의 함수 리터럴도 할당문이 실행되는 시점에 평가되어 함수 객체가 된다
즉, 함수 표현식은 함수 호이스팅이 아니라 변수 호이스팅이 발생
함수 호이스팅
함수를 호출하기 전에 반드시 함수를 선언해야 한다는 규칙을 무시한다.=> 함수 표현식을 사용할 것 권장
12.4.4 Function 생성자 함수
생성자? 무엇을 생성하지?
생성자 함수: 객체를 생성하는 함수
문자열로 매개변수와 몸체를 전달
var k = new Function('x', 'y', 'return x + y');
console.log(k(1,2))
Function 생성자 함수로 함수를 생성하는 방법은 일반적이지 않고 바람직하지도 않다. (클로저를 생성하지 않음)
12.4.5 화살표 함수
생성자 함수로 사용할 수 없다.
기존 함수와 this 바인딩 방식이 다르다.
prototype 프로퍼티가 없다.
arguments 객체를 생성하지 않는다=>화살표 함수는 스코프를 갖지 않기 때문에, 화살표 함수 내부에서 arguments 객체에 접근할 수 없다는 의미
Rest 파라미터와 arguments 객체
공통점
- 함수에서 인자의 개수가 가변적일 때 사용
차이점
(1) Rest 파라미터 => 매개변수(인자)를 적어야 하고(...rest) , 배열 메서드 사용 가능(map, filter 등)
function foo(a,b, ... rest){
console.log(a);
console.log(b);
console.log(rest);
rest.map(item => console.log(item));
}
(2) arguments 객체 => 매개변수(인자)를 안 적는다, 배열 메서드 사용 불가능
function boo(){
console.log(arguments);
arguments.map(item => console.log(item)); //
}
12.5 함수 호출
12.5.1 매개변수와 인수
- 매개변수(parameter)==인자
- 인수(argument)
매개변수를 통해 인수를 전달. 인수는 매개변수에 할당된다.
매개변수는 함수를 정의할 때 선언, 인수는 함수를 호출할 때 지정
함수가 호출된 이후,
(1) 암묵적으로 매개변수가 생성
(2) undefined로 초기화
(3) 인수가 순서대로 할당
만약 인수가 부족하다면?=> 할당되지 않은 매개변수의 값은 undefined
만약 인수가 매개변수 개수를 초과한다면?=> 버려지지 않음. arguments 객체의 프로퍼티로 보관
12.5.2 인수 확인
자바스크립트는
(1) 인수의 개수가 일치하는지 확인하지 않는다
(2) 인수의 타입을 확인하지 않는다
=> 에러는 런타임 때 발생
문제를 해결하기 위해,
(1) 타입 검사
(2) 단축 평가로 기본 값 할당(함수 몸체 내부에서 진행)
(3) 매개변수 기본값(매개변수에서 할당)
단축 평가란, 논리 연산자를 사용할 때, 왼쪽 피연산자만으로 결과를 알 수 있는 경우 오른쪽 피연산자를 평가하지 않고 바로 연산 결과를 반환하는 것을 말합니다. |
false || console.log('이 코드는 실행됩니다.'); // (1)
true || console.log('이 코드는 실행되지 않습니다.'); //(2)
(1)은 왼쪽이 false이기 때문에 오른쪽도 검사를 한다.
(2)는 왼쪽이 true이기 때문에 오른쪽을 검사하지 않는다.
12.5.3 매개변수의 최대 개수
"이상적인 함수는 한 가지 일만 해야 한다."
"가급적 작게 만들어야 한다."
"이상적인 매개변수 개수는 0개"
=> 3개 이상을 넘지 않길 권장
만약 매개변수가 그 이상인 경우, 객체를 인수로 전달하는 방법을 사용할 것
=>하지만 이 경우, 함수 내부에서 객체를 변경하면 함수 외부의 객체가 수정되는 side effect 발생
12.5.4 반환문
함수의 실행 결과를 함수 외부로 반환
함수 호출은 표현식이다?
=> 함수 호출이 값으로 평가되는 것을 의미.
=> 함수가 값을 반환하면, 함수 호출 표현식의 값은 반환된 값
12.6 참조에 의한 전달과 외부 상태의 변경
매개변수에 복사되어 전달되는건 같지만, 원시타입의 경우 값이 전달되고, 객체 타입 인수는 참조 값(=참조하는 주소)가 복사되어 전달=> side effect 발생 가능! => 깊은 복사 사용으로 원본 객체를 복제
12.7 다양한 함수의 형태
12.7.1 즉시 실행 함수
기명함수를 정의하고 그룹 연산자 없이 호출한 경우? 왜 에러 발생? => 함수 블록코드의 닫는 중괄호 뒤에 세미콜론이 암묵적으로 추가되기 때문.
12.7.2 재귀 함수
12.7.3 중첩 함수
중첩함수 == 내부함수 => 외부함수를 돕는 헬퍼 함수 역할
외부함수 ↔ 내부함수
12.7.4 콜백 함수
"함수의 합성"
(1) 함수에서 변하지 않는 공퉁 로직은 미리 정의
(2) 변경되는 로직은 추상화해서 함수 외부에서 함수 내부로 전달
=> 추상화의 예시: f(x)
콜백 함수: 함수의 매개변수를 통해 다른 함수의 내부로 전달되는 함수.
고차 함수: 매개 변수를 통해 함수의 외부에서 콜백 함수를 전달 받은 함수
고차 함수는 콜백 함수를 자신의 일부분으로 합성.(중첩 함수는 고정되어 있어서 교체 X)
12.7.5 순수 함수와 비순수 함수
불변성 지향=> 안정성↑
순수 함수
동일한 인수가 전달되면 동일한 값을 반환하는 함수
최소 하나 이상의 인수를 전달 받는다
외부 상태를 변경하지 않는다
비순수 함수
외부 상태에 따라 반환값이 달라지는 함수(=외부 상태에 의존하는 함수)
부수 효과(side effect)를 갖는다
18장 함수와 일급 객체
18.1 일급 객체
(1) 무명의 리터럴로 생성 가능(런타임때 생성)
(2) 변수나 자료구조(객체, 배열 등)에 저장 가능
(3) 함수의 매개변수에 전달 가능
(4) 함수의 반환값으로 사용 가능
함수 == 일급 객체
즉, 함수를 객체와 동일하게 사용 가능=> 함수는 값과 동일하게 취급
객체와 차이점
(1) 객체는 호출 불가능
(2) 함수 객체는 함수 고유의 프로퍼티를 소유
18.2 함수 객체의 프로퍼티
18.2.1 arguments 프로퍼티
유사 배열 객체
초과된 인수 뿐만 아니라, 모든 인수가 암묵적으로 arguments 객체의 프로퍼티로 보관됨
프로퍼티 키는 인수의 순서를 나타냄
함수가 호출될 때, 인수 개수를 확인하는 방법으로 사용
"유사 배열 객체"이기 때문에 배열 메서드를 사용 불가능 => Rest 파라미터 도입 이유
18.2.2 caller 프로퍼티
함수 자신을 호출한 함수를 가리킴
18.2.3 length 프로퍼티
함수를 정의할 때 선언한 매개변수의 개수
arguments 객체의 length 프로퍼티 ≠ 함수 객체의 length 프로퍼티
arguments 객체의 length 프로퍼티: 인자(argument)의 개수
함수 객체의 length 프로퍼티: 매개변수(parameter)의 개수
function foo(a,b,c){
console.log('arguments.length: ',arguments.length) //(1)
}
console.log('foo.length: ',foo.length) //(2)
18.2.4 name 프로퍼티
함수 이름
- 기명 함수 표현식
=> 함수 이름. (식별자 아님)
- 익명 함수 표현식
ES5: 빈 문자열
ES6: 식별자
- 함수 선언문
18.2.5 __proto__ 접근자 프로퍼티
18.2.6 prototype 프로퍼티
constructor 만이 소유하는 프로퍼티
prototype 프로퍼티는 함수가 객체를 생성하는 생성자 함수로 호출될 때 생성자 함수가 생성할 인스턴스의 프로토타입 객체를 가리킴