study: javascript | 숨참고 deep dive (18) 함수와 일급 객체

Lumpen·2023년 2월 24일
0

Study

목록 보기
20/92

일급 객체

다음과 같은 조건을 만족하면 일급객체다

  1. 무명의 리터럴로 생성할 수 있다 (런타임에 생성 가능)
  2. 변수나 자료구조 (객체, 배열 등) 에 저장할 수 있다
  3. 함수의 매개변수로 전달할 수 있다
  4. 함수의 반환값으로 사용할 수 있다

자바스크립트의 함수는 위 조건을 모두 만족하므로 일급 객체다

함수가 일급 객체라는 것은 함수를 객체와 동일하게 사용할 수 있다
따라서 함수는 값을 사용할 수 있는 곳 (변수 할당문, 객체의 프로퍼티 값, 배열 요소,
함수 호출의 인수, 함수 반환문) 이라면 어디든지 리터럴로 정의할 수 있고
런타임에 함수 객체로 평가된다
일급 객체로서 함수가 가지는 가장 큰 특징은
일반 객체와 같이 함수의 매개변수에 전달할 수 있고 반환값으로도 사용할 수 있다는 것으로
함수형 프로그래밍을 가능하게 하는 자바스크립트의 장점 중 하나다
함수는 객체이지만 일반 객체와 달리 호출할 수 있다
또 함수 고유의 프로퍼티를 소유한다

함수 객체의 프로퍼티

함수는 객체다
따라서 함수도 프로퍼티를 가질 수 있다
함수의 프로퍼티도 Obejct.getWonPropertyDescriptors 메서드로 확인해볼 수 있다

arguments, caller, length, name, prototype 프로퍼티는
모두 일반 객체에 없는 함수 객체 고유의 프로퍼티다
하지만 __proto__ 프로퍼티는 접근자 프로퍼티로 함수 객체의 프로퍼티가 아니라
Object.prototype 객체의 프로퍼티는 모든 객체가 상속받아 사용할 수 있다
즉 __proto__ 접근자 프로퍼티는 모든 객체에서 사용할 수 있다

arguments 프로퍼티

함수 객체의 arguments 프로퍼티의 값은 arguments 객체다
arguments 객체는 함수 호출 시 전달된 인수들의 정보를 담고 있는
순회 가능한 유사 배열 객체로 함수 내부에서 지역 변수처럼 사용된다
즉 외부에서는 참조할 수 없다

arguments 프로퍼티는 일부 브라우저에서 지원하고있지만 ES3 부터 표준에서 빠졌다
Function.arguments 같은 사용법은 권장되지 않으며
arguments 객체를 참조하도록 한다

자바스크립트는 함수의 매개변수와 인수의 개수가 일치하는지 확인하지 않는다
함수를 정의할 때 선언한 매개변수는 함수 몸체 내부에서 변수와 동일하게 취급된다
즉 함수가 호출되면 함수 몸체 내에서 암묵적으로 매개변수가 선언되고
undefined 로 초기화 후 인수가 할당된다

선언된 매개변수의 수 보다 인수를 저겍 전달했을 경우
전달되지 않은 매개변수는 undefined
매개변수의 수 보다 많은 인수를 전달했을 경우 초과된 인수는 무시된다

arguments 객체는 인수를 프로퍼티 값으로 소유하며 프로퍼티 키는 인수의 순서를 나타낸다
arguments 객체의 callee 프로퍼티는 arguments를 생성한 함수 자신을 가리키고
length 는 인수의 개수를 가리킨다

자바스크립트의 함수는 인수의 개수를 체크하지 않기 때문에
arguments.length 가 유용하게 사용될 수 있다
arguments 객체는 매개변수 개수를 확정할 수 없는 가변 인자 함수를 구현할 떄 유용하다

arguments 객체는 배열 형태를 띄지만 배열이 아닌 유사 배열 객체다
유사 배열 객체는 for 문으로 순회 가능한 객체를 말한다

ES6 에서 도입된 이터레이션 프로토콜을 준수하면 순회 가능한 자료구조인 이터러블이 된다
ES6 부터 arguments 객체는 유사배열객체이면서 이터러블이 된다

이터레이션 프로토콜

유사배열객체는 뱌ㅐ열이 아니므로 배열 메서드를 사용할 수 없다
.call(), .apply() 를 사용해 간접 호출해야 한다

ES6 에서 Rest 파라미터 (나머지 매개변수) 의 도입으로 arguments 객체의 중요성이 이전 같지 않다
누군가는 ES5 를 사용하기 때문에..

caller 플고퍼티

caller 프로퍼티는 ECMAScript 사양에 포함되지 않은 비표준 프로퍼티다
표준화될 예정이 없기 떄문에 지나친다

length 프로퍼티

함수 객체의 length 프로퍼티는 함수의 매개변수 개수를 가리킨다

name 프로퍼티

함수 객체의 name 프로퍼티는 함수의 이름을 나타낸다
ES6 부터 정식으로 표준이 되었다

name 프로퍼티는 ES5와 ES6 의 동작이 다르기 때문에 주의해야 한다
익명 함수 표현식의 경우 ES5 에서 빈 문자열이지만
ES6 에서는 함수 객체를 가리키는 식별자를 값으로 갖는다

함수 이름과 함수 객체를 가리키는 식별자는 다르다는 것을 잊지 말자

// 기명 함수 표현식

const namedFunc = function foo() {} 
console.log(namedFunc.name); // foo

const anonymousFunc = function() {} 
// ES5: 빈 문자열
// 함수 객체를 가리키는 변수의 이름을 갖는다

function bar() {}
console.log(bar.name) // bar

__proto__ 접근자 프로퍼티

모든 객체는 [[Prototype]] 이라는 내부 슬롯을 갖는다
객체지향 프로그래밍의 상속을 구현하는 프로토타입 객체를 가리킨다
__proto__ 접근자 프로퍼티는 [[Prototype]] 내부 슬롯이 가리키는
프로토타입 객체에 접근하기 위해 사용하는 접근자 프로퍼티다
내부 슬롯에는 직접 접근할 수 없고 이와 같은 접근 방법을 제공하는 경우
간접적으로 접근할 수 있다

const obj = { a: 1 }
console.log(obj.__proto__ === Object.prototype) // true

console.log(obj.hasOwnProperty('a')) // true
console.log(obj.hasOwnProperty('__proto__') // false

prototype 프로퍼티

prototype 프로퍼티 생성자 함수로 호출할 수 있는 함수 객체로
constuctor 만이 소유하는 프로퍼티다
non-consturctor 에는 prototype 프로퍼티가 없다
prototype 프로퍼티는 함수가 객체를 생성하는 생성자 함수로 호출될 때
생성자 함수가 생성할 인스턴스의 프로토타입 객체를 가리킨다

profile
떠돌이 생활을 하는. 실업자는 아니지만, 부랑 생활을 하는

0개의 댓글