함수(Function)이란 어떤 작업을 수행하기 위해 필요한 문(Statement)들의 집합을 정의한 코드블록이다.
function add() {
let sum = 3 + 3;
return sum;
}
함수는 이름과 매개변수를 갖으며 필요한 때에 호출하여 코드 블록에 담긴 문들을 일괄적으로 실행할 수 있다.
함수의 이름에 괄호 '( )'를 붙어주면 된다
▶ 소스
function add() {
let sum = 3 + 3;
return sum;
}
add();
▶ 결과
함수를 호출하면, 그제서야 add()함수를 실행하여 '3 + 3'인 '6'을 변수에 저장하고 'sum'으로 반환한다
function checkCorrect() {
let hi = "안녕하세요";
return hi;
}
console.log(checkCorrect());
▶ 결과
▶ Parameter(매개변수) : 함수를 정의하는 코드에서 괄호안에 정의하고 있는 변수
▶ Agrument(인자) : 함수를 호출하는 곳에서 함수에 전달하는 값
function add(x,y) { // add라는 명의 함수, x, y의 parameter
var total = x + y;
retrun total;
}
console.log(10, 20) // argument(인자) 10, 20
일반적으로 프로그래밍 언어에서 함수 선언과 비슷한 형식
// 문법
function 함수명() {
구현 로직
}
// 예시
function funcDeclarations() {
return 'A function declaration';
}
funcDeclarations(); // 'A function declaration'
▶ 소스예제
function square(number) {
return number * number;
}
square();
▶ 결과
함수의 일급객체 특성을 이용하여 함수 리터널 방식으로 함수를 정의하고 변수에 할당할 수 있는데 이러한 방식을 함수 표현식(Function expression)이라 한다.
// 문법
var 함수명 = function () {
구현 로직
}
// 예시
var funcExpression = function () {
return 'A function expression';
}
funcExpression(); // 'A function expression'
▶ 소스예제
var square = function(number) { return number * number };
square(3);
▶ 결과
화살표 함수 표현(arrow function expression)은 this, arguments, super 또는 new.taget을 바인딩 하지 않는다.
화살표 함수는 function 키워드 대신 화살표(=>)를 사용하여 간략한 방법으로 함수를 선언한다.
'return'선언없이 반환이 가능하다.
▶ ES 5 소스
//ES_1
var pow = function (x) { return x * x; };
console.log(pow(10)); // 100
//ES_2
var arr = [1, 2, 3];
var pow = arr.map(function (x) { // x는 요소값
return x * x;
});
▶ ES 6 소스
//ES6_1
const pow = x => x * x;
console.log(pow(10)); // 100
//ES_2
const arr = [1, 2, 3];
const pow = arr.map(x => x * x);
console.log(pow); // [ 1, 4, 9 ]
함수안에 있는 선언들을 먼저 모두 끌어올려서 해당 *함수유효범위의 최상단에 선언하는 것을 말함
자바스크립트는 Parser가 함수 실행 전 해당 함수를 전체적으로 한번 흝는다.
함수 안에 존재하는 변수/함수 선언에 대한 정보를 메모리에 저장하고 기억해 두었다가 호출했을 시 실행시킨다.
*함수유효범위 : 함수 블록 { } 을 말함
즉, 함수 내에서 아래쪽에 존재하는 내용 중 필요한 값들을 끌어 올리는 것
실제로 코드가 끌어올려지는 건 아니며, 자바스크립트 Parser 내부적으로 끌어올려서 처리한다
실제 메모리에서는 변화가 없다
▶ 호이스팅 대상
var 변수 선언와 함수 선언문에서만 호이스팅이 일어난다
var변수/함수의 선언만 위로 끌어 올려지며, 할당은 끌어 올려지지 않는다
let/const 변수 선언과 함수 표현식(function expression)에서는 호이스팅이 발생하지 않는다.
▶ 소스예제#1 var변수 먼저 호출 시;
my name;
var myname; // [Hoisting] "선언"
▶ 소스예제#1 결과
▶ 소스예제#2 let 변수 먼저 호출 시;
myname = "HEEE"; // "할당"
let myname2 = "HEEE2"; // [Hoisting] 발생 X
▶ 소스예제#2 결과
▶ 소스예제#3 함수선언식에서 함수 먼저 호출 시
;
foo();
function foo() {
console.log('hello');
};
▶ 소스예제#3 결과
▶ 소스예제#4 함수 표현식에서 함수 먼저 호출 시;
foo();
var foo = function() {
console.log('hello');
};
▶ 소스예제#4 결과 : Syntax Error
▶ 소스예제#5 함수 선언식에서 함수 내 호출;
function printName(firstname) { // 함수선언문
var result = inner(); // "선언 및 할당"
console.log(typeof inner); // > "function"
console.log("name is " + result); // > "name is inner value"
function inner() { // 함수선언문
return "inner value";
}
}
printName(); // 함수 호출
//////////////////////////////////////////////
function printName(firstname) {
var result; // [Hoisting] var 변수 "선언"
function inner() { // [Hoisting] 함수선언문
return "inner value";
}
result = inner(); // "할당"
console.log(typeof inner); // > "function"
console.log("name is " + result); // > "name is inner value"
}
printName();
▶ 소스예제#5 결과
▶ 소스예제#6 함수표현식의 선언이 호출보다 위에 있는 경우;
function printName(firstname) { // 함수선언문
var inner = function() { // 함수표현식
return "inner value";
}
var result = inner(); // 함수 "호출"
console.log("name is " + result);
}
printName(); // > "name is inner value"
/////////////////////////////////////////////
function printName(firstname) {
var inner; // [Hoisting] 함수표현식의 변수값 "선언"
var result; // [Hoisting] var 변수값 "선언"
inner = function() { // 함수표현식 "할당"
return "inner value";
}
result = inner(); // 함수 "호출"
console.log("name is " + result);
}
printName(); // > "name is inner value"
▶ 소스예제#6 결과
▶ 소스예제##7 함수표현식의 선언이 호출보다 아래에 있는 경우(var변수에 할당);
/* 오류 */
function printName(firstname) { // 함수선언문
console.log(inner); // > "undefined": 선언은 되어 있지만 값이 할당되어있지 않은 경우
var result = inner(); // ERROR!!
console.log("name is " + result);
var inner = function() { // 함수표현식
return "inner value";
}
}
printName(); // > TypeError: inner is not a function
/////////////////////////////////////////////
/** --- JS Parser 내부의 호이스팅(Hoisting)의 결과 --- */
/* 오류 */
function printName(firstname) {
var inner; // [Hoisting] 함수표현식의 변수값 "선언"
console.log(inner); // > "undefined"
var result = inner(); // ERROR!!
console.log("name is " + result);
inner = function() {
return "inner value";
}
}
printName(); // > TypeError: inner is not a function
▶ 소스예제#7 결과 : TypeError
▶ 소스예제#8 : 함수 표현식의 선언이 호출보다 아래에 있는 경우 (let/const 변수에 할당);
function printName(firstname) { // 함수선언문
console.log(inner); // ERROR!!
let result = inner();
console.log("name is " + result);
let inner = function() { // 함수표현식
return "inner value";
}
}
printName(); // > ReferenceError: inner is not defined
▶ 소스예제#8 결과 : ReferenceError
▶ 호이스팅 우선순위
같은 이름의 var변수 선언과 함수 선언에서의 호이스팅
▶ 소스예제#1
var myName = "hi";
function myName() {
console.log("yuddomack");
}
function yourName() {
console.log("everyone");
}
var yourName = "bye";
console.log(typeof myName);
console.log(typeof yourName);
/** --- JS Parser 내부의 호이스팅(Hoisting)의 결과 --- */
// 1. [Hoisting] 변수값 선언
var myName;
var yourName;
// 2. [Hoisting] 함수선언문
function myName() {
console.log("yuddomack");
}
function yourName() {
console.log("everyone");
}
// 3. 변수값 할당
myName = "hi";
yourName = "bye";
console.log(typeof myName); // > "string"
console.log(typeof yourName); // > "string"
▶ 결과
▶ 소스예제#2: 값이 할당되지 않은 변수와 값이 할당되어 있는 변수에서의 호이스팅
var myName = "Heee"; // 값 할당
var yourName; // 값 할당 X
function myName() { // 같은 이름의 함수 선언
console.log("myName Function");
}
function yourName() { // 같은 이름의 함수 선언
console.log("yourName Function");
}
console.log(typeof myName); // > "string"
console.log(typeof yourName); // > "function"
▶ 소스예제#2 결과:
값이 할당되어 있지 않은 변수는 함수선언문이 변수를 덮어쓴다
값이 할당되어 있는 변수의 경우, 변수가 함수선언문을 덮어쓴다
클로저(closure)는 내부함수가 외부함수의 맥락(context)에 접근할 수 있는 것을 가르킴
부함수가 외부 함수 안에서 정의된 모든 변수와 함수들을 완전하게 접근 할 수 있도록 승인(그리고 외부함수가 접근할수 있는 모든 다른 변수와 함수들까지) 그러나 외부 함수는 내부 함수 안에서 정의된 변수와 함수들에 접근 할 수 없음
▶ 소스예제#1 : 내부함수
function outter(){
function inner(){
var title = 'coding everybody';
console.log(title);
}
inner();
}
outter();
▶ 소스예제#1 결과
▶ 소스예제#2
function outter(){
var title = 'coding everybody';
function inner(){
console.log(title);
}
inner();
}
outter();
▶ 소스예제#2 결과
outter(); 함수내 inner(); 함수가 정의되어 있다. 함수inner();를 내부 함수라한다
inner(); 함수에서 title을 호출했을 때, 외부함수인 outter();함수의 지역변수에 접근할 수 있음을 보여준다.
▶ 소스예제#3
function outter(){
var title = 'coding everybody';
return function(){
console.log(title);
}
}
inner = outter();
inner();
▶ 소스예제#3 결과
![image.png](https://velog.velcdn.com/post-images%2Finyong_pang%2F6f846a90-1b64-11ea-a08c-f18e394da52d%2Fimage.png)
- 변수 inner는 outter();함수를 호출하고 있다.
- inner에는 변수가 없이 호출을 하는데, 지역변수가 소멸되는 것이 아니라 외부함수의 지역변수인 var title를 사용하여 내부함수를 호출하고 있다.
- 외부함수는 외부함수의 지역변수를 사용하는 내부함수가 소멸될 때까지 소멸되지 않는다
▶ 소스예제#4 : 객체의 메소드에서 클로저
```javascript
function factory_movie(title){
return {
get_title : function (){
return title;
},
set_title : function(_title){
title = _title
}
}
}
ghost = factory_movie('Ghost in the shell');
matrix = factory_movie('Matrix');
console.log(ghost)
console.log(matrix)
console.log(ghost.get_title());
console.log(matrix.get_title());
ghost.set_title('공각기동대');
console.log(ghost.get_title());
console.log(matrix.get_title());
▶ 소스예제#4 결과
factory_movie();함수는 객체를 반환한다. 그 객체는 메소드로 get_title();함수와 set_title();함수를 가지고 있다. 이 메소드들은 외부함수인 factory_movie(); 함수에서 인자값을 전달받는다
ghost.set_title('공각기동대'); 에 의해 set_title은 외부함수 factory_movie의 지역변수 title의 값을 '공각기동대'로 변경하였다. 즉, ghost.get_title();의 값이 '공각기동대'로 변경된다는 것은 set_title();함수와 get_title();함수가 title의 값을 공유하고 있다는 의미
외부함수가 실행될 때마다 새로운 지역변수를 포함하는 클로저가 생성되기 때문에 ghost와 matrix는 서로 완전히 독립된 객체이다
factory_movie();의 지역변수 title은 2행에 선언된 객체의 메소드에서만 접근할 수 있는 값
Javascript는 기본적으로 private한 속성을 지원하지 않는데, 클로저의 이러한 특성으로 private한 속성을 사용할 수 있게 된다.
▶ 소스예제#5 : 클로저응용
var arr = []
for(var i = 0; i < 5; i++){
arr[i] = function(){
return i;
}
}
for(var index in arr) {
console.log(arr[index]());
}
▶ 소스예제#5 결과
▶ 소스예제#5 수정
var arr = []
for(var i = 0; i < 5; i++){
arr[i] = function(id) {
return function(){
return id;
}
}(i);
}
for(var index in arr) {
console.log(arr[index]());
}
▶ 소스예제#5 수정 결과
첫번째 for문안에서 arr[i]함수가 내부적으로 인자를 전달하기 위해 id라는 매개변수를 지정한다
지정된 id매개변수가 지역변수 역할을 하여, 가장안에 있는 내부함수가 외부함수 지역변수에 retrun하고 retrun된 값으로 두번째 for문을 통해 0 ~ 4까지 출력함
함수 작성에 익숙해지셨나요?
아래의 설명을 듣고 함수를 작성해주세요.
함수 이름은 checkYear입니다.
올해 년도를 return합니다.
년도를 작성할 때는 ""(쌍따옴표)없이 숫자만 4자리 써주세요
▶ 소스
function checkYear() {
const year = 2019;
return year;
}
console.log(checkYear());
▶ 결과