#18. 일급 객체

해피데빙·2022년 8월 18일
0

1. 일급 객체

  1. 무명의 리터럴로 생성할 수 있다. 즉, 런타임에 생성이 가능하다
  2. 변수나 자료구조(객체, 배열 등)에 저장할 수 있다
  3. 함수의 매개변수에 전달할 수 있다
  4. 함수의 반환값으로 사용할 수 있다
  • 다시 말해 함수를 객체와 동일하게 사용할 수 있다는 의미
    (즉 값과 동일하게 취급할 수 있다)
  • 함수는 값을 사용할 수 있는 곳이라면 어디서든지 리터럴로 정의할 수 있다
  • 런타임에 함수 객체로 평가된다

함수의 일급 객체로서 가지는 가장 큰 특징

  • 일반 객체와 같이 함수의 매개변수에 전달할 수 있다
  • 함수의 반환값으로 사용할 수 있다
  • 함수형 프로그래밍을 가능케 하는 자바스크립트의 장점

함수의 일반 객체와의 차이

  • 일반 객체와 달리 호출할 수 있다
  • 함수 고유의 프로퍼티 소유

ex. 자바스크립트의 함수

const increase = function (num){ 
	return ++num;
}

const decrease = function (num){
	return --num;
}

const auxs = {increase, decrease}

function makeCounter(aux){ 
	let num =0; 
    
    return function (){ 
    	num = aux(num); 
        return num;
    };
}

const increaser = makeCounter(auxs.increase); 
console.log(increaser()); 
console.log(increaser()); 

const decreaser = makeCounter(auxs.decrease); 
console.log(decreaser()); 

2. 함수 객체의 프로퍼티

함수는 객체
즉 프로퍼티를 가질 수 있다

function square(number){ 
	return number * number
}

console.dir(square)

square함수의 모든 프로퍼티의 프로퍼티 어트리뷰트를 확인해보면
: arguments, caller, length, name, prototype 프로퍼티

  • 모두 함수 객체의 데이터 프로퍼티
  • 일반 객체에는 없는 함수 객체 고유 프로퍼티
  • 함수 고유의 프로퍼티가 아니라 Object.prototype 객체의 프로퍼티는 모든 객체가 상속받아 사용할 수 있다 (proto는 접근자 프로퍼티 )
  • Object.prototype 객체의 proto 접근자 프로퍼티는 모든 객체가 사용할 수 있다

함수 객체의 프로퍼티들

1. arguments 프로퍼티

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

함수 객체의 arguments 프로퍼티의 한계

  • 일부 브라우저에서 지원
  • ES3부터 표준에서 폐지되었다
  • 따라서 Functions.arguments와 같은 사용법은 권장되지 않다
  • 함수 내부에서 지역 변수처럼 사용할 수 있는 arguments 객체를 참조하도록 한다

매개변수와 인수의 개수 차이 발생 시

  • 함수의 매개변수와 인수의 개수가 일치하는지 확인하지 않는다
  • 따라서 함수 호출 시 매개변수 개수만큼 인수를 전달하지 않아도 에러 발생 X
  • 매개변수는 함수 몸체 내부에서 변수와 동일하게 취급된다
    : 함수 호출 시 함수 몸체 내에서 암묵적으로 매개변수가 선언되고 undefined로 초기화 이후 인수 할당
    : 적게 전달 시 매개변수는 undefined로 초기화된 상태로 유지
    : 매개변수의 개수보다 인수를 더 많이 전달한 경우 초과된 인수는 무시된다
    : arguments 객체의 프로퍼티로 모든 인수들이 보관된다

arguments 객체는 인수를 프로퍼티 값으로 소유, 프로퍼티 키는 인수의 순서를 나타낸다
arguments 객체의 callee 프로퍼티
: 호출되어 arguments 객체를 생성한 함수 즉 함수 자신을 가리킨다
: arguments 객체의 length는 인수의 개수를 가리킨다

cf. arguments 객체의 Symbol.iterator 프로퍼티

arguments 객체의 Symbol 프로퍼티
: arguments 객체를 순회 가능한 자료구조인 이터러블로 만들기 위한 프로퍼티

function muliply(x,y){
	const iterator = arguments[Symbol.iterator]();
    
    
    
    //next 메서드를 호출하여 이터러블 객체 arguments를 순회 
	console.log(interator.next()) //{value: 1, done: false}
    console.log(interator.next()) //{value: 2, done: false
    console.log(interator.next()) //{value: 3, done: false
    
    return x * y
}

multiply(1,2,3) //1,2,3이라는 인수를 돌면서 value는 1이 나오고 done(순회가 끝난지에 대한 의미)

가변 인자 함수
자바스크립트는 매개변수의 개수, 호출 시 전달 인수의 개수를 확인하지 않는다
함수 호출 시 인수 개수 확인하고 이에 따라 함수의 동작을 달리 정의하는 함수
이때 arguments 사용

function sum(){ 
let res = 0; 
for(let i=0; i<arguments.length; i++){
	res += arguments[i]
}

return res; 
}

console.log(sum()) //0
console.log(sum(1,2));//3
console.log(sum(1,2,3)) //6

arguments 객체

  • 유사 배열 객체
  • length 프로퍼티를 가진 객체로 for문으로 순회할 수 있는 객체
  • ES6부터 arguments 객체는 유사 배열 객체면서 동시에 이터러블 (순회 가능 자료구조)
  • 즉 배열이 아니므로 배열 메서드 사용할 수 없고 간접 호출해야 한다
  • 이를 해결하기 위해 ES6부터는 Rest 파라미터를 도입했다
function sum(...args){
	return args.reduce((pre, cur) => pre + cur, 0); 
}
console.log(sum(1,2)); //3

2. caller 프로퍼티

  • ECMAScript 사양에 포함되지 않은 비표준 프로퍼티
  • 표준화될 예정도 없는 프로퍼티
  • 별로 안 중요함
  • 함수 자신을 호출한 함수를 가리킨다
function foo(func){ 
	return func();
}

function bar(){ 
	return 'caller:' + bar.caller;
}

console.log(foo(bar)); //caller : function foo(func){...}
console.log(bar()); //caller: null

Node.js환경에서 실행하면 다른 결과가 나온다. 모듈이기 때문에!

3. length 프로퍼티

함수 객체의 length 프로퍼티는 함수 정의 시 선언한 매개변수의 개수
arguments 객체의 length 프로퍼티와 함수 객체의 length 프로퍼티 값은 다를 수 있다

  • arguments: 인자의 개수
  • 함숫 객체 : 매개변수의 개수
function bar(x){
	return x;
}
console.log(bar.length); //1

function baz(x,y){ 
return x*y
}
console.log(baz.length); //2

4. name 프로퍼티

함수 이름을 나타낸다

  • ES6에서 정식 표준이 되었다 : 함수 객체를 가리키는 식별자
  • ES5와 동작이 다르다 : 익명 함수 표현식의 경우 빈문자열
//기명 함수 표현식
var namedFunc = function foo(){}; 
console.log(namedFunc.name); //foo 

//익명 함수 표현식
var anonFunc = function(){ };
console.log(anonFunc.name)//ES6:anonFunc(변수 이름), ES5:빈 문자열

//함수 선언문
fuction bar(){} 
console.log(bar.name); //bar

함수 이름과 함수 객체를 가리키는 식별자는 의미가 다르다
함수를 호출할 때는 함수 이름이 아닌 함수 객체를 가리키는 식별자로 호출 ?

5. proto 접근자 프로퍼티

[[Prototype]]

  • 모든 객체가 갖는 내부 슬롯
  • 객체 지향 프로그래밍의 상속을 구현하는 프로토타입 객체를 가리킨다
  • 내부 슬롯은 직접 접근할 수 없고 간접적인 접근 방법(여기서는 proto)을 통해서만 접근 가능
  • proto : prototype 내부 슬롯이 가리키는 프로토타입 객체에 접근하기 위해 사용하는 접근자 프로퍼티
  • 객체 리터럴 방식으로 생성한 객체는 프로토타입 객체인 Object.prototype의 프로퍼티를 상속받는다

6. prototype 프로퍼티

  • 생성자 함수로 호출할 수 있는 함수 객체
  • constructor만이 소유하는 프로퍼티
  • 일반 객체와 생성자 함수로 호출할 수 없는 non-constructor에는 prototype 프로퍼티가 없다
//함수 객체는 prototype 프로퍼티를 소유한다
(function(){}).hasOwnProperty('prototype'); //true

//일반 객체는 prototype 프로퍼티를 소유하지 않는다 
({}).hasOwnProperty('prototype');//false

함수

  • 선언문, 표현식 : constructor
  • 화살표, 메서드 : non-constructor

선언문 : 런타임 이전에 함수 객체가 생성(함수 객체로 초기화 / 함수 호이스팅)
표현식 : var add가 먼저 선언이 되고, undefined로 저장이 된다(undefined로 초기화가 된다/ 변수 호이스팅 : undefined)

profile
노션 : https://garrulous-gander-3f2.notion.site/c488d337791c4c4cb6d93cb9fcc26f17

0개의 댓글