절차형 프로그래밍 위에서 객체지향 프로그래밍이 탄생한 것.
절차형 프로그래밍이 갖고 있는 부족함을 객체지향 프로그래밍이 보완해주는 역할.
절차형 프로그래밍은 함수가 있고, 객체지향 프로그래밍 또한 함수가 있지만 '객체'라는 개념이 등장함.

함수 바깥 환경을 조작해선 안됨 = side effect 를 만들지 않는다.
(side effect란 부수효과 라는 뜻으로, 지금 수행중인 작업으로 인해 외부의 데이터가 바뀌게 되는것을 말한다.)
같은 입력값에 대해 항상 같은 값을 리턴한다. = 랜덤함수, Date 객체 등은 함수 내부에서 사용하지 않는다.
사용하려면 함수 밖같에서 수행하고 그 결과를 함수의 인자로 전달하자.
한번에 한가지 작업만 한다. = 성격이 조금이라도 다른 작업이라면 if 로 나누지 말고
함수를 하나 더 만들어 코드를 분리시킨다.
데이터의 불변성을 유지한다. = 인자로 받은 값을 직접 바꾸지 않고 복사본을 만들어 조작한다. (1번과 겹치는 개념)
인자로 받은 값이 배열이나 객체같은 참조타입 이라면 .slice() .filter() .map() 이나 {...param} 로 복사한뒤 작업하자.
정리하면, 순수함수는 외부에 어떤 영향도 끼치지 않고 한가지 일만 하고 끝나는 함수.
Lexical scope는 함수를 어디서 선언하였는지에 따라 상위 스코프를 결정하는 것이다. 중요한 점은 함수의 호출이 아니라 함수의 선언에 따라 결정된다는 점이다.
function makeFunc() {
var name = "Mozilla";
function displayName() {
alert(name);
}
return displayName;
}
var myFunc = makeFunc();
//myFunc변수에 displayName을 리턴함
//유효범위의 어휘적 환경을 유지
myFunc();
//리턴된 displayName 함수를 실행(name 변수에 접근)
이 코드는 displayName()함수가 실행되기 전에 외부함수인 makeFunc()로부터 리턴되어 myFunc 변수에 저장된다는 것이다.
alert가 동작한다!!
한 눈에 봐서는 이 코드가 여전히 작동하는 것이 직관적으로 보이지 않을 수 있다. 몇몇 프로그래밍 언어에서, 함수 안의 지역 변수들은 그 함수가 처리되는 동안에만 존재한다. makeFunc() 실행이 끝나면(displayName함수가 리턴되고 나면) name 변수에 더 이상 접근할 수 없게 될 것으로 예상하는 것이 일반적이다.
하지만 위의 예시와 자바스크립트의 경우는 다르다. 그 이유는 자바스크립트는 함수를 리턴하고, 리턴하는 함수가 클로저를 형성하기 때문이다. 클로저는 함수와 함수가 선언된 어휘적 환경의 조합이다. 이 환경은 클로저가 생성된 시점의 유효 범위 내에 있는 모든 지역 변수로 구성된다. 첫 번째 예시의 경우, myFunc은 makeFunc이 실행 될 때 생성된 displayName 함수의 인스턴스에 대한 참조다. displayName의 인스턴스는 변수 name 이 있는 어휘적 환경에 대한 참조를 유지한다. 이런 이유로 myFunc가 호출될 때 변수 name은 사용할 수 있는 상태로 남게 되고 "Mozilla" 가 alert 에 전달된다.
myFunc는 makeFunc 함수 호출해서 리턴값으로 받은 displayName 함수를 값으로 가지고있구요
myFunc를 호출하는 시점에는 displayName 함수 내부의 스코프만 알 수 있을거란 생각을해서 displayName 내부의 name변수는 선언이 안된상태다라고 착각할 수 있지만,
함수를 호출한 시점이아니라 함수를 선언한 (작성한) 시점의 렉시컬 스코프를 참조할 수 있기때문에 함수 선언 시점에 선언된 name변수 참조가 가능하다는 말인거같아요
var counter = (function() {
var privateCounter = 0;
function changeBy(val) {
privateCounter += val;
}
return {
increment: function() {
changeBy(1);
},
decrement: function() {
changeBy(-1);
},
value: function() {
return privateCounter;
}
};
})();
console.log(counter.value()); // logs 0, 이미 선언된 함수이기 때문에 값을 참조할 수 있다
//각 카운터가 호출될 때마다; 하나의 클로저에서 변수 값을 변경해도 다른 클로저의 값에는 영향을 주지 않는다.
counter.increment();
counter.increment();
console.log(counter.value()); // logs 2
counter.decrement();
console.log(counter.value()); // logs 1
출처
https://developer.mozilla.org/ko/docs/Web/JavaScript/Closures
https://velog.io/@majaeh43/%EC%A0%88%EC%B0%A8%EC%A7%80%ED%96%A5-%EA%B0%9D%EC%B2%B4%EC%A7%80%ED%96%A5-%ED%95%A8%EC%88%98%ED%98%95-%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%B0%8D
https://kwangsunny.tistory.com/32
https://ontheway.tistory.com/69?category=1232424
https://velog.io/@ksh4820/Lexical-scoped%EC%99%80-%ED%81%B4%EB%A1%9C%EC%A0%80