✔ 일련의 과정을 문으로 구현하고 코드 블록으로 감싸서 하나의 실행 단위로 정의한 것
✔ 함수 이름을 호출X -> 함수 객체를 가리키는 식별자 호출O
✔ 일급 객체이다 = 함수를 값처럼 자유롭게 사용할 수 있다.
✔ 함수 호스트잉 = 함수 선언문이 코드의 선두로 끌어 올려진 것처럼 동작하는 자바스크립트 고유의 특징
1. 함수 선언문
function add(x,y){
return x+y;
}
✔ 함수 이름 생략 불가
✔ 표현식이 아닌 문
✔ 함수 리터럴을 단독으로 사용 -> 함수 선언문
// 기명 함수 리터럴을 단독 사용 -> 함수 선언문
function foo() { console.log('foo');}
foo(); // foo
// 함수 리터럴을 피연산자로 사용 -> 함수 리터럴 표현식
(function bar() { console.log('bar');});
bar(); // ReferenceError: bar is not defined
2. 함수 표현식
// var add(식별자) = function add(함수이름)(x,y)
var add = function add(x,y){
return x+y;
};
console.log(add(2,5)); //7
//console.log(add(식별자)(2,5))
✔ 변수에 할당되는 값이 함수 리터럴인 문
✔ 함수 이름 생략 = 익명함수
✔ 표현식인 문
✔ 함수 호스트잉 X -> 변수 호스트잉 O
✔ 반드시 함수 표현식 이후에 참조 또는 호출
✔ 함수 선언문 보다 함수 표현식 권장
3. Function 생성자 함수
var add = new Function('x','y','return x+y');
console.log(add(2,5)); //7
✔ Function 생성자 함수에 매개변수 목록과 함수 몸체를 문자열로 전달하면서 new 연산자와 함께 호출하면 함수 객체를 생성해서 반환
4. 화살표 함수(ES6)
var add = (x,y) => x+y;
console.log(add(2,5)); //7
}
✔ function 키워드 대신 화살표 사용
✔ 항상 익명 함수로 정의
(function(){ //주로 사용
//...
}());
(function(){
//...
})();
!function(){
//...
}();
+function(){
//...
}();
var factorial = function foo(n){
if(n<=1)
return 1;
return n * factorial(n-1);
};
console.log(factorial(5)); 120
function outer(){
var x = 1
//중첩 함수
function inner(){
var y = 2;
//외부 함수의 변수를 참조 할 수 있음
console.log(x+y); //3
}
inner();
}
outer();
function repeat(n){
for(var i = 0; i<n; i++)
console.log(i);
}
repeat(5); // 0 1 2 3 4
//순수 함수
var count = 0; //현재 count를 나타내는 상태
// increase는 동일한 인수가 전달되면 언제나 동일한 값 반환
function increase(n){
return ++n;
}
// 순수 함수가 반환한 결과값을 변수에 재할당해서 상태 변경
count = increase(count);
console.log(count); //1
count = increase(count);
console.log(count); //2
//비순수 함수
var count = 0; //increase 함수에 의해 변화
// 외부 상태에 의존하여 외부 상태를 변경
function increase(){
return ++count;
}
// 외부 상태(count)를 변경하므로 상태 변화를 추적하기 어려움
increase();
console.log(count); //1
increase();
console.log(count); //2
✔ 식별자가 유효한 범위
✔ 식별자를 검색하는 규칙
전역 - 코드의 가장 바깥 영역 / 전역 스코프 / 전역 변수
✔ 전역 변수는 어디서든지 참조 가능
지역 - 함수 몸체 내부 / 지역 스코프 / 지역 변수
✔ 지역 변수는 자신의 지역 스코프와 하위 지역 스코프에서 유효
✔ 스코프가 계층적으로 연결된 것
✔ 스코프가 함수의 중첩에 의해 계층적 구조를 가짐
✔ 변수를 참조할 때 자바스크립트 엔진은 스코프 체인을 통해 코드의 스코프 -> 상위 스코프으로 이동하며 선언된 변수를 검색
✔ 함수 레벨 스코프 - var 키워드로 선언된 변수는 오로지 함수의 코드 블록(함수 몸체)만을 지역 스코프로 인정
var i =10;
//for 문에서 선언한 i는 전역 변수이다. 이미 선언된 전역 변수 i가 있으므로 중복 선언
for(var i = 0; i<5; i++){
console.log(i); // 0 1 2 3 4
}
console.log(i); //5, i의 값이 변경됨
자바스크립트는 렉시컬 스코프이다.
✔ 동적 스코프 - 함수를 어디서 호출했는지에 따라 함수의 상위 스코프 결정
✔ 렉시컬 스코프(정적 스코프) - 함수를 어디서 정의했는지에 따라 함수의 상위 스코프 결정, 함수의 상위 스코프는 언제나 자신이 정의된 스코프
var x = 1;
function foo(){
var x = 10;
bar();
}
//전역에서 정의 -> 자신이 기억하고 있는 전역스코프를 상위 스코프로 사용
function bar(){
console.log(x);
}
foo(); //1
bar(); //1
지역 변수의 생명 주기 = 함수의 생명 주기
전역 변수의 생명 주기 = 더 이상 실행할 문이 없을 때 종료
✔ var 키워드로 선언한 전역 변수 생명 주기
= 전역 객체의 생명 주기 = 웹 페이지를 닫을 때까지 유효
암묵적 결합 - 모든 코드가 전역 변수를 참조하고 변경
-> 코드의 가독성이 나빠지고 의도치 않게 변경될 수 있음
긴 생명 주기 -> 메모리 리소스도 오래 기간 소비
스코프 체인 상에서 종점에 존재 - 전역 변수의 검색 속도가 가장 느림
-> 변수를 검색할 때 전역 변수가 가장 마지막에 검색 됨
네임스페이스 오염 - 파일이 분리되어 있어도 전역 스코프를 공유함
변수의 스코프는 좁을수록 좋다 -> 지역 변수 사용
(function(){
var foo = 10; // 즉시 실행 함수의 지역 변수
//...
}());
console.log(foo); // ReferenceError
var MYAPP={}; // 전역 네임스페이스 객체
MYAPP.person={
name: 'Lee';
address: 'Seoul';
};
console.log(MYAPP.person.name); //Lee
var Counter = (function(){
//private 변수
var num = 0;
//외부로 공개할 데이터나 메서드를 프로퍼티로 추가한 객체 반환
return{
increase(){
return ++num;
},
decrease(){
return --num;
}
};
}());
console.log(Counter.num); //undefined : private변수는 외부로 노출 x
console.log(Counter.increase()); //1
console.log(Counter.increase()); //2
console.log(Counter.decrease()); //1
<script type="module" src="lib.mjs"></script>
<script type="module" src="app.mjs"></script>