본문 바로가기

javascript

Javascript 함수에 관하여...

함수 선언문 / 함수 표현식 / Function() 생성자 함수

함수 선언문과 함수 표현식에서 함수를 생성하는 함수 리터럴 개념

 

함수 리터럴

자바스크립트에서는 함수도 일반 객체처럼 값으로 취급된다. 객체 리터럴 방식으로 일반 객체를 생성

할 수  있는 것 처럼 함수 리터럴을 이용해 함수를 생성할 수 있다.

 

function 키워드 : 자바스크립트 함수 리터럴은 function 키워드로 시작한다.

함수명은 함수 몸체의 내부 코드에서 자신을 재귀적으로 호출하거나 자바스크립트 디버거가

해당 함수를 구분하는 식별자로 사용된다.

함수명은 선택 사항이라는 것이다. 함수명이 없는 함수를 익명 함수라 한다.

function add(x,y) {

 return x + y;

}

함수 선언문 방식으로 함수 생성하기

함수 선언문 방식은 앞에서 설명한 함수 리터럴 형태와 같다.

함수 선언문 방식으로 정의된 함수의 경우는 반드시 함수명이 정의되어 있어야 한다.

 

함수도 하나의 값처럼 취급된다. 따라서 자바스크립트 함수는 일급 객체라고 한다.

 

함수 표현식 방식으로 함수 생성하기

함수도 하나의 값처럼 취급된다. 따라서 자바스크립트 함수는 일급 객체라고 한다.

 

따라서 함수도 숫자나 문자열 처럼 변수에 할당하는 것이 가능하다.

이런 방식으로 함수 리터럴로 하나의 함수를 만들고, 여기서 생성된 함수를 변수에 할당하여 함수를 생성하는 것을

함수 표현식이라고 말한다.

다음은 add() 함수를 함수 표현식 형태로 생성한 것이다.

const add = function (x,y) {
	return x + y;
};

const plus = add;

console.log(add(3,4)) // output : 7
console.log(plus(5,6)) // output : 11

함수 표현식은 함수 선언문 문법과 거의 유사하다. 유일한 차이점은 함수 표현식 방법에서는 함수 이름이 선택 사항이며,

보통 사용하지 않는다는 것이다.

 

add 변수는 함수 리터럴로 생성한 함수를 참조하는 변수 / 함수 이름이 아니다.

함수 변수 add는 함수의 참조값을 가지므로, 다른 변수에도 그대로 할당할 수 있다.

함수 표현식으로 생성된 함수를 호출하려면 함수 변수를 사용해야한다.

 

익명 함수 표현식  <=> 기명 함수 표현식

 

const add = function sum(x,y) {
	return x + y;
};

console.log(add(3,4)) // output : 7
console.log(sum(3,4)) // ReferenceError : sum is not defined

함수 표현식에서 사용된 함수 이름은 정의된 함수 내부에서 해당 함수를 재귀적으로 호출하거나, 디버거 등에서 

함수를 구분할 때 사용된다.

따라서, 함수 이름으로 사용된 sum 으로 함수 외부에서 해당 함수를 호출할 때 sum() 함수가 정의되어 있지 않다는

에러가 발생한다. 함수 선언문 형식으로 정의된 add() 함수는 자바스크립트 엔진에 의해 다음과 같은 함수 표현식 형태로 변경되기 때문이다.

const add = function add (x,y) {
	return x + y;
};

함수 이름과 함수 변수의 이름이 add로 같으므로, 함수 이름으로 함수가 호출되는 것처럼 보이지만,

실제로는 add 함수 변수로 함수 외부에서 호출이 가능하게 된 갓이다.

< add() 함수 선언문의 실제 구조 >

 

add 함수 변수 -> add 함수

 

앞서 설명했듯이 함수 표현식에서는 함수 이름이 선택 사항이지만, 이러한 함수 이름을 사용하면,

함수 코드 내부에서 함수 이름으로 함수의 재귀적인 호출 처리가 가능하다.

 

함수 선언문과 표현식에서의 세미콜론?

함수 선언문 방식으로 add() 함수를 정의할 때는 함수 끝에 ; 세미콜론을 따로 붙이지 않았지만,

함수 표현식 방식으로 정의 할때는 함수 끝에 붙인 것을 발견할 수 있다.

 

일반적으로 함수 선언문 방식에서는 선언된 함수 끝에 세미 콜론을 붙이지 않지만,

함수 표현식 방식의 경우는 세미콜론을 붙이는 것을 권장한다.

 

왜? 그럴까 이유는 아래와 같다.

 

const func = function() {
	return 42;
} // 표현식이지만 끝에 세미콜론 안 붙임
(function() {
	console.log("Hello")
})()

---------

func(*)()

* -> 즉시 실행함수가 담겨있지만, 그냥 Js 파서가 세미콜론으로 구분짓지 않아 호출 괄호로 인식한다.

따라서 func 이 호출되고,
42가 반환되면서,
아래와 같이 되고,

42() number is not a function

세미콜론을 해주면 에러가 해결된다.

Function() 생성자 함수를 통한 함수 생성하기

자바스크립트 함수도 Function() 이라는 기본 내장 생성자 함수로부터 생성된 객체 라고 볼 수 있다.

앞서 설명한 함수 선언문이나 함수 표현식 방식도 Function() 생성자 함수가 아닌 함수 리터럴 방식으로

함수를 생성하지만, 결국엔 이 또한 내부적으로는 Function() 생성자 함수로 함수가 생성된다고 볼 수 있다.

 

Function() 생성자 함수로 함수를 생성하는 문법은 다음과 같다.

new Function ( arg1, arg2, ... argN, functionBody)

- arg1, arg2, ... argN 함수의 매개변수

- functionBody 함수가 호출될 때 실행될 코드를 포함한 문자열

 

const add = new Function("x", "y", "return x + y");
console.log(add(3,4)) // 출력값 7

상식선으로 알고 넘어가자

 

함수 호이스팅

 

자바스크립트 함수 생성에 있어서 핵심 가이드에서 함수 표현식 사용을 권하고 있다.

이유는 함수 호이스팅 때문이다.

 

add(2,3) // 5

function add(x,y) {
	return x + y;
}

add(3,4); // 7

함수 선언문 형태로 정의한 함수의 유효 범위는 코드의 맨 처음부터 시작한다는 것을 확인 할 수 있다.

이것을 함수 호이스팅이라고 한다.

 

더글러스 크락포드는 함수 호이스팅은 함수를 사용하기 전에 반드시 선언해야 한다는 규칙을 무시하므로

코드의 구조를 엉성하게 만들 수 있다고 지적한다.

그래서 함수 표현식을 권장하고 있다.

 

함수 호이스팅이 발생하는 원인은 자바스크립트의 변수 생성과 초기화의 작업이 분리돼서 진행되기 때문이다.

 

자바스크립트에서 함수도 객체이다.

함수도 객체다. 아래 코드를 보자

 

function add(x,y) {
	return x + y;
}

add() 함수 객체에 result, status 프로퍼티 추가

add.result = add(3,2);
add.status = "OK";

console.log(add.result) // 5
console.log(add.status) // "OK"

result와 status 프로퍼트를 추가하는 게 가능하다는 것을 보여준다.

 

add() 함수를 생성할 때 함수 코드는 함수 객체의 [[ Code ]] 내부 프로퍼티에 자동으로 저장된다.

 

따라서 자바스크립트에서 함수는

1. 특정 기능의 코드를 수행하는 역할

2. 일반 객체처럼 자신의 프로퍼티를 가질 수 있는 특별한 객체 라고 볼 수 있다.

 

함수 객체의 최종 모습이다. add() 함수가 함수 본연의 기능인 코드를 포함하고 있는 [[ Code ]] 프로퍼티와

일반 객체처럼 result와 status 프로퍼티를 가지는 것을 확인할 수 있다.

자바스크립트에서 함수는 값으로 취급된다.

함수도 일반 객체처럼 취급될 수 있다는 것을 말한다.

 

따라서 다음과 같은 동작이 가능하다.

 

1. 리터럴에 의해 생성

2. 변수나 배열의 요소, 객체의 프로퍼티 등에 할당 가능

3. 함수의 인자로 전달 가능

4. 함수의 리턴값으로 리턴 가능

5. 동적으로 프로퍼티를 생성 및 할당 가능

 

이 같은 특징이 있으므로 자스에서는 함수를  일급 객체라고 부른다.

일급 객체라는 말은 컴퓨터 프로그래밍 언어 분야에서 쓰이는 용어이다.

앞에서 나열한 기능이 모두 가능한 객체를 일급 객체라고 부른다.

 

일급 객체의 특성으로 함수형 프로그래밍이 가능하다.

 

함수의 프로토타입

함수 객체의 표준 프로퍼티는 name, caller, arguments, length, prototype 프로퍼티 등을 가져야한다.

name 프로퍼티 = > 함수의 이름을 나타낸다.

caller 프로퍼티 = > 자신을 호출한 함수를 나타낸다. add() 함수를 호출해주지 않았으므로 null 값이 나온다.

arguments 프로퍼티 => 함수를 호출할 때 전달된 인자 값을 나타낸다.

 

자바스크립트는 프로토 타입 언어이다. 그래서 참조값은 모두 [[prototype]] 프로퍼티를 가진다.

함수 역시 객체이고 [[prototype]] 프로퍼티를 가진다. __proto__와 같은 프로퍼티이다.

 

함수 객체의 부모 역할을 하는 프로토타입 객체를 Function.prototype 객체라고 하며 이것 역시도 함수 객체라고 정의

하고 있다. 크롬 브라우저에서는 Function Prototype 객체를 Empty() 함수라고 명하고 있으며,

이것 또한 함수 객체이므로 add() 함수와 마찬가지로 name, caller, arguments 함수 객체의 프로퍼티가 있다.

추가로 Function.prototype 객체가 가지는 프로퍼티와 메서드는 상속하여 어떤 함수 객체에서나 사용가능하다.

constructor 프로퍼티

toString() 메서드

apply 메서드

call 메서드

bind 메서드

 

특히 apply(), call() 는 실제로 자주 사용되는 중요한 메서드 이므로 call / apply 메서드를 이용한 명시적인 this 바인딩에 대해 알아볼 것이다.

 

함수객체의 length 프로퍼티는 함수 정의할때 정의된 매개변수의 개수를 나타낸다.

 

function fn0 () {
 //
}

function fn1(x) {
 return x;
}

function fn2(x,y) {
 return x + y;
}

console.log(fn0.length) // 0
console.log(fn1.length) // 1
console.log(fn2.length) // 2

 

arguments 객체 ???