#참조에 의한 전달과 외부 상태의 변경
매개변수는 함수 몸체 내부에서 변수와 동일하게 취급되므로 매개변수 또한 타입에따라 값에 의한 전달, 참조에 의한 전달 방식을 그대로 따른다.
//매개변수 primitive는 원시 값을 전달받고, 매개변수 obj는 객체를 전달받는다.
function changeVal(primitive, obj){
primitive += 100;
obj.name = 'Kim';
}
//외부 상태
var num = 100;
var person = {name: 'Lee'};
console.log(num); //100
console.log(person); //{name: "Lee"}
//원시 값은 값 자체가 복사되어 전달되고 객체는 참조 값이 복사되어 전달된다.
changeVal(num, person);
//원시 값은 원본이 훼손되지 않는다.
console.log(num); //100
//객체는 원본이 훼손된다.
console.log(person); //{name: "Kim"}
-원시 값은 변경 불가능한 값이기 때문에 재할당을 통해 새로운 원시 값으로 대체했고 , 객체 타입 인수를 전달받은 매개변수 obj의 경우 객체는 변경 가능한 값이므로 직접 변경할 수 있기 때문에 재할당 없이 직접 할당된 객체를 변경했다.
2022.03.13 - [Front-end/JavaScript] - [JavaScript_DeepDive] 11. 원시 값과 객체의 비교
[JavaScript_DeepDive] 11. 원시 값과 객체의 비교
자바스크립트가 제공하는 7가지 데이터 타입(숫자, 문자열, 불리언, null, undefined, 심벌, 객체 타입)은 크게 원시타입(primitive type)과 객체 타입(object/reference type)으로 구분할 수 있고 크게 세가지 측
ddvuutk.tistory.com
-함수가 외부상태(객체를 할당한 person변수)를 변경하면 상태 변화를 추적하기 어려워진다. 그렇게 되면 코드의 복잡성을 증가시키고 가독성을 해치는 원인이 된다.
-여러 변수가 참조에 의한 전달 방식을 통해 참조 값을 공유하고 있다면 이 변수들은 언제든지 참조하고 있는 객체를 직접 변경할 수 있다. 객체의 변경을 추적하는 것은어려운 일이므로 객체를 불변객체로 만들어 사용하는 것이 해결방법 중 하나이다.(원시값처럼 불가능한 값으로)
-필요한 경우 객체를 완전히 복제(깊은 복사)를 통해 새로운 객체를 생성하고 재할당을 통해 교체한다. 이렇게 하면 부수효과를 없앨 수 있다. -외부상태를 변경하지 않고 외부 상태에 의존하지도 않는 함수를 순수함수라고 한다. 순수함수를 통해 부수효과를 최대한 억제하여 오류를 피하고 프로그램의 안전성을 높이려는 프로그램을 패러다임 함수형 프로그래밍이라고 한다.
#다양한 함수의 형태
※즉시 실행 함수
함수의 정의와 동시에 즉시 호출되는 함수를 즉시 실행 함수(IIFE, Immediately Invoked Function Expression)라고 한다. 즉시 실행 함수는 단 한번만 호출되며 다시 호출할 수 없다. 익명함수를 사용하는 것이 일반적
-즉시 실행함수도 일반 함수처럼 값을 반환할 수 있고 인수를 전달할 수도 있다.
//익명 즉시 실행 함수
(function(){
var a = 3;
var b = 5;
return a*b;
}());
//기명 즉시 실행 함수
(function foo(){
var a = 3;
var b = 5;
return a*b;
}());
foo(); //ReferenceError: foo is not defined
그룹연산자(...)내의 기명함수는 함수 선언문이 아니라 함수 리터럴로 평가되며 함수 이름은 함수 몸체에서만 참조할 수 있는 식별자이므로 즉시 실행 함수를 다시 호출할 수는 없다.
-익명 즉시 함수를 그룹 연산자 없이 실행하면 함수 선언문의 형식에 맞지 않기 떄문에 에러가 난다. 기명함수도 그룹 연산자 없이 사용하면 자바스크립트 엔진이 코드 중괄호 뒤에 세미콜론을 암묵적으로 붙이기 때문에 에러가 발생한다.
function foo() {}(); //=>function foo() {};();
위 코드의 함수 뒤에 ()는 그룹연산자로 해석되고, 그룹연산자에 피연산자가 없기 때문에 에러가 발생한다.
※재귀함수(recursive function)
함수가 자기 자신을 호출하는 것을 재귀호출(recursive call)이라 한다. 재귀 함수는 자기 자신을 호출하는 행위, 즉 재귀 호출을 수행하는 함수를 말한다.
-재귀함수는 반복뒤는 처리를 위해 사용한다.
-대표적인 예로 팩토리얼과 피보나치 함수가 있다.
var factorial = function foo(n){
//탈출 조건 : n이 1이하일 때 재귀호출을 멈춘다.
if(n<=1) return 1;
//함수를 가리키는 식별자로 자기 자신을 재귀 호출
return n * factorial(n-1);
//함수 이름으로 자기 자신을 재귀 호출할 수도 있다.
//console.log(factofial ===foo); //true
//return n * foo(n-1);
};
console.log(factorial(5)); //5!= 5 * 4 * 3 * 2 * 1 = 120
-factorial 함수 내부에서 자기 자신을 호출할 때 사용한 식별자 factorial은 함수 이름이다. 함수 이름은 함수 몸체 내부에서만 유효하다. 따라서 함수 내부에서는 함수 이름을 사용해 자기 자신을 호출할 수 있다.(식별자로도 가능)
-함수 외부에서 함수를 호출할 때는 반드시 함수를 가리키는 식별자로 해야 한다.
-재귀함수는 자기 자신을 무한 재귀호출 하기 때문에 탈출 조건(if문 사용)을 만들어야 한다. 탈출 조건이 없으면 스택오버플로우(stack overflow)에러가 발생한다. 직관적으로 이해하기 쉬울 때만 한정적으로 재귀 함수 사용
※중첩 함수(nested function)
함수 내부에 정의된 함수를 중첩함수 또는 내부 함수라고 한다. 그리고 중첩함수를 포함하는 함수는 외부함수라 부른다.
중첩함수는 외부함수 내부에서만 호출할 수 있다. 일반적으로 중첩함수는 자신을 포함하는 외부함수를 돕는 헬퍼함수의 역할을 한다.
※콜백함수
함수의 매개변수를 통해 다른 함수의 내부로 전달되는 함수를 콜백함수(callback function)이라고 하며, 매개변수를 통해 함수의 외부에서 콜백 함수를 전달받은 함수를 고차함수(Higher-Order function)라고 한다.
-중첩함수처럼 콜백함수도 고차함수에 전달되어 헬퍼함수의 역할을 한다. 중첩함수는 교체하기 어렵지만 콜백함수는 함수 외부에서 내부로 주입하기 때문에 자유롭게 교체할 수 있다. 고차함수는 콜백함수를 자신의 부분으로 함성한다.
-콜백함수는 고차함수에 의해 호출되며 이때 고차 함수는 필요에 따라 콜백 함수에 인수를 전달할 수 있다.
//익명 함수 리터럴을 콜백 함수로 고차함수에 전달한다
//익명 함수 리터럴은 rep[eat 함수를 호출할 때마다 평가되어 함수 객체를 생성한다.
repeat(5, function(i){
if(i%2)console.log(i);
}); //1 3
//logOdds 함수는 단 한 번만 생성된다.
var logOdds = functoin(i){
if(i%2) console.log(i);
};
//고차 함수에 함수 참조를 전달한다
repeat(5, logOdds); //1 3
콜백 함수를 익명 함수 리터럴로 정의하면서 곧바로 고차 함수에 전달하면 고차 함수가 호출될 때마다 콜백 함수가 생성된다.
-콜백함수는 함수형 프로그래밍 패러다임뿐만 아니라 비동기 처리(이벤트 처리, Ajax통신, 타이머 함수 등)에 활용되는 중요한 패턴이다.
//콜백 함수를 사용한 이벤트 처리
//myButton 버튼을 클릭하면 콜백 함수를 실행한다.
document.getElementById('myButton').addEventListener('click', function(){
console.log('button clicked!');
});
//콜백 함수를 사용한 비동기 처리
//1초 후에 메세지를 출력한다
setTimeout(function (){console.log('1초 경과');}, 1000);
※순수 함수와 비순수 함수
외부상태 - 전역 변수, 서버 데이터, 파일, Console, DOM등
순수함수(pure function) : 어떤 외부 상태에 의존하지도 않고 변경하지도 않는 부수 효과가 없는 함수
-순수함수는 동일한 인수가 전달되면 언제나 동일한 값을 반환
-최소 하나 이상의 인수를 전달받는다. 인수를 전달받지 않는 순수함수는 언제나 동일한 값을 반환하므로 상수(const)와 마찬가지다. (순수함수 의미 상실)
-함수형 프로그래밍은 순수함수와 보조 함수의 조합을 통해 외부 상태를 변경하는 부수효과를 최소화 하는 불변성을 지향하는 프로그래밍 패러다임이다.
비순수함수(imputre function) : 외부 상태에 의존하거나 외부 상태를 변경하는 부수효과가 있는 함수
-함수의 외부 상태에 따라 반환값이 달라진다
-함수의 복잡성을 증가시킨다
'Javascript > JavaScript_스터디' 카테고리의 다른 글
| [JavaScript_DeepDive] 14. 전역변수의 문제점 (0) | 2022.03.17 |
|---|---|
| [JavaScript_DeepDive] 13. 스코프(scope) (0) | 2022.03.16 |
| [JavaScript_DeepDive] 12. 함수(1) (0) | 2022.03.14 |
| [JavaScript_DeepDive] 11. 원시 값과 객체의 비교 (0) | 2022.03.13 |
| [JavaScript_DeepDive] 10. 객체 리터럴 (0) | 2022.03.13 |
댓글