목표
- 18장의 내용을 최대한 이해하고 정리하기
다음 조건을 만족하는 객체를 말한다.
함수는 위의 조건을 모두 만족하므로 일급 객체이다.
// 함수는 무명의 리터럴로 생성할 수 있으며 변수에 저장할 수 있다.
const increase = function(num) {
return num++;
};
const decrease = function(num) {
return num--;
};
// 함수는 객체에 저장할 수 있다.
const operations = { increase, decrease };
// 함수의 반환값으로 사용될 수 있다.
function makeCounter(operation) {
let num = 0;
return function() {
num = operation(num);
return num;
};
}
// 함수의 매개변수에 전달할 수 있다.
const increaser = makeCounter(operations.increase);
console.log(increaser());
// 결과
1
함수형 프로그래밍
- 순수 함수와 보조 함수의 조합을 통해 외부 상태의 변경을 최소화해서 불변성(Immutability)을 지향하는 프로그래밍 패러다임을 말한다.
- 쉽게 말하면 깔끔하고 유지보수가 용이하게 하기위해 효과적으로 함수를 사용하는 것을 말한다.
함수는 객체이지만 일반 객체와는 차이점이 있다.
함수만이 가지고 있는 프로퍼티를 살펴보면 다음과 같다.
function add(num) {
return num + num;
}
console.dir(add);
console.log(Object.getOwnPropertyDescriptors(add));
// 결과
{
length: { value: 1, writable: false, enumerable: false, configurable: true },
name: { value: 'add', writable: false, enumerable: false, configurable: true },
arguments: { value: null, writable: false, enumerable: false, configurable: false },
caller: { value: null, writable: false, enumerable: false, configurable: false },
prototype: { value: {}, writable: true, enumerable: false, configurable: false }
}
arguments의 프로퍼티 값은 arguments 객체이다.
arguments의 객체는 함수 호출 시 전달된 인수들의 정보를 담고 있는 순회 가능한(iterable) 유사 객체 배열이며, 함수 내부에서 지역 변수처럼 사용된다. (즉, 함수 외부에서는 참조할 수 없다.)
함수 내부에서 arguments 객체를 찍어보면 다음과 같은 결과를 확인할 수 있다.
function multiply(x, y) {
console.log(arguments)
return x * y;
}
multiply();
multiply(1);
multiply(1, 2);
// 결과
Arguments [callee: ƒ, Symbol(Symbol.iterator): ƒ]
Arguments [1, callee: ƒ, Symbol(Symbol.iterator): ƒ]
Arguments(2) [1, 2, callee: ƒ, Symbol(Symbol.iterator): ƒ]
function foo(func) {
return func();
}
function bar() {
return `caller: ${bar.caller}`;
}
console.log(foo(bar));
console.log(bar());
// 브라우저에서의 결과
"caller: function foo(func) { ... }"
"caller: null"
✏️ 참고
- 위 코드를 Node.js 환경에서 실행해보면 다르게 출력된다. 이는 모듈과 관련이 있다.
function foo() {}
function bar(x) {
return x;
}
function baz(x, y) {
return x + y;
}
console.log(foo.length);
console.log(bar.length);
console.log(baz.length);
// 결과
0
1
2
💡 주의
- arguments 객체의 length와 함수 객체의 length는 다를 수 있으므로 주의해야 한다.
- arguments 객체의 length는 인자의 개수를 가리키고 함수 객체의 length는 매개변수의 개수를 가리킨다.
const func1 = function foo() {};
const func2 = function func2() {};
function func3 () {};
console.log(func1.name);
console.log(func2.name);
console.log(func3.name);
// 결과
"foo"
"func2"
"func3"
const object = { num: 1 };
console.log(object.__proto__ === Object.prototype);
console.log(object.hasOwnProperty('num'));
console.log(object.hasOwnProperty('__proto__'));
// 결과
true
true
false
hasOwnProprty
- 인수로 전달받은 프로퍼티 키가 객체 고유의 프로퍼티일 경우 true를 반환하고 상속받은 포로토타입의 프로퍼티 키인 경우 false를 반환한다.
(function() {}).hasOwnProperty('prototype');
({}).hasOwnProperty('prototype');
// 결과
true
false