1. 함수 기반 스코프
각각의 선언된 함수는 각자의 버블을 생성하지만 다른 자료 구조도
자체적인 스코프를 생성하지 않나는 것은 사실이 아니다.
함수 스코프는 모든 변수가 함수에 속하고 함수 전체(중첩 스코프 포함)에 걸쳐 사용, 재사용된다.
2. 일반 스코프에 숨기
스코프를 통해 숨는 이유는 여러가지 있지만,
소프트웨어 디자인 원칙인 '최소 권한의 원칙'*('최소 권위', '최소 노출' 으로도 불림)과 관련있다.
* : 모듈 / 객체의 API와 같은 소프트웨어를 설계할 때 필요한 것만
최소한으로 남기고 나머지는 숨겨야 한다는 것
모든 변수, 함수가 글로벌 스코프에 존재하면 최소 권위에 반하는 규칙이다.
const func1 = (a) => {
const func2 = (a) => {
return a - 1;
}
let b;
b = a + func2(a * 2);
console.log(b * 3);
}
func1(2); // 15
위의 코드처럼 작성하는 코드가 더 나은 코드라고 본다.
충돌 회피
변수와 함수를 스코프 안에 숨기면 같은 이름을 갖은 서로 다른 확인자가 충돌할 일이 없다는 것이다.
자연스럽게 같은 확인자 이름을 사용하게 되며 스코프를 이용해
내부에 선언문을 숨기는 것이 유일하고 좋은 방법이다.
글로벌 네임스페이스
글로벌 스코프에서 하나의 고유 이름을 갖는 객체 선언문을 생성한다.
이때 생성한 객체는 네임스페이스로 사용된다.
네임스페이스를 통해 최상위 스코프의 확인자가 아니라 속성 형태로 라이브러리의 기능이 노출된다.
모듈 관리
특정 스코프로부터 의존성 관리자를 이용하면 확인자를 글로벌 스코프에 추가할 필요없이
명시적인 방법으로 확인자를 가져와 사용할 수 있다.
주의할 점은, 이러한 도구를 이용한다 해서 렉시컬 스코프 규직에서 벗어나지 못한다.
의존성 관리자는 여기서 설명한 스코프 규칙을 적용해 모든 확인자가
공유 스코프에 노출되는 것을 방지하고, 우발적 스코프 충돌을 방지하기 위해
충돌위험이 없는 비공개 스포크에 확인자를 보관한다.
3. 스코프 역활을 하는 함수
기본적으로 함수를 사용할 때 함수를 선언해야 한다.
이렇게 함수를 선언하는 경우 함수의 이름을 둘러싼 스코프를 오염시킨다 한다.
그리고 그 함수를 직접 이름으로 호출해야만 실행할 수 있다는 것이다...
다행히 이러한 문제는 JS에서 해결 가능하다.
var a = 2;
(const func1 = () => {
var a = 3;
console.log(a); // 3
})();
console.log(a); // 2
이 코드에서 함수는 선언문이 아니라 함수 표현식으로 취급받는다.
함수 선언문과 함수 표현식의 중요한 차이는 함수 이름이
어디의 확인자로 묶이느냐와 관련있다.
함수 이름을 자기 내부에 숨기면 함수를 둘러싼 스코프를 불필요하게 요염시키지 않는다.
익명 vs 기명
흔히 사용하는 함수 표현식중 콜백 인자로 함수를 보낼때 사용하는 것이 익명 함수 표현식이라한다.
setTimeout( () => {
console.log('익명 함수 표현식');
}, 1000);
함수 표현식에서는 이름을 빼도 되지만, 함수 선언문에서는 이름이 빠지면 문법에 맞지 않는다.
함수 표현식에서 외워야할 단점이 있다.
1️⃣ - 익명함수는 스택 추적 시 표시할 이름이 없어 디버깅이 어려울 수 있다.
2️⃣ - 이름 없이 함수 스스로 재귀 호출을 하면 폐기 예정인 arguments.callee 참고가 필요하다.
3️⃣ - 기능을 잘 나타내는 이름을 생략하기에 이해하고 읽기 어려울 수 있다.
함수 표현식 즉시 호출하기
이것은 다양한 방법으로 함수 표현식 호출이 가능하다.
var a = 2;
(const func1 = () => {
var a = 3;
console.log(a); // 3
})();
console.log(a); // 2
var a = 2;
(const func1 = (global) => {
var a = 3;
console.log(a); // 3
console.log(global.a); // 2
})(window);
console.log(a); // 2
var a = 2;
(cosnt IIFE = (def) => {
def(window);
})(const func1 = (global) => {
var a = 3;
console.log(a); // 3
console.log(global.a); // 2
});
console.log(a); // 2
마지막 코드의 경우 함수 표현식 def는 코드 후반부에 정의되어
코드 전반부에 정의된 IIFE 함수에 인자로 넘겨진다.
결국, 인자 함수 def가 호출되고 window가 global 인자로 넘겨진다.
'JavaScript > You Don't know JS' 카테고리의 다른 글
I don't know JS YET) 호이스팅 (0) | 2022.12.23 |
---|---|
I don't know JS YET) 함수 vs 블록 스코프 - 2 (0) | 2022.12.23 |
I don't know JS YET) 렉시컬 스코프 (0) | 2022.12.16 |
I don't know JS YET) 스코프란 무엇인가 (0) | 2022.12.15 |
JS 복습 1주차 / 4. 강제 변환 Coercion (0) | 2022.11.07 |