JavaScript에서 스코프는
변수의 유효범위
로 사용된다.
바깥쪽 스코프에서 선언한 변수는 안쪽 스코프에서 사용 가능
하지만 안쪽 스코프에서 선언한 변수는 바깥쪽 스코프에서 사용 할 수 없다.스코프는 중첩이 가능하다.
가장 바깥쪽의 스코프는 특별히 전역 스코프(Global scope)
라 하고 전역이 아닌 다른 스코프는 모두 지역 스코프(Local scope)
이다.지역 변수
, 전역 스코프에서 선언한 변수는 전역 변수
라 한다. 이 때, 지역 변수는 전역 변수보다 더 높은 우선 순위
를 가진다.let name = '김코딩'; // 전역 변수
function showName(){
let name = '박해커'; // 지역 변수
console.log(name);
}
console.log(name); // 김코딩
showName(); // 박해커
// 지역변수와 전역변수의 이름이 같지만 지역변수의 우선순위가 높으므로 지역변수 name이 출력
// 동일한 변수 이름으로 인해 바깥쪽 변수가 안쪽 변수에 의해 가려지는 쉐도잉 현상
console.log(name); //김코딩
스코프의 종류에는
블록 스코프(block scope)
와함수 스코프(function scope)
가 있다.
let
과 var
방식의 차이/// let으로 선언
for ( let i = 0; i < 5; i++ ){
console.log(i) // 다섯번 반복
}
console.log('final i:', i); // ReferenceError
// 블록스코프 안에서 정의된 변수 i는 블록 범위를 벗어나는 즉시 접근할수 없음
👉 var
선언 방식은 블록 스코프를 무시
하고, 함수 스코프만 따른다.
하지만 화살표 함수의 블록 스코프는 무시하지 않는다.
// var로 선언
for ( var i = 0; i < 5; i++ ){
console.log(i) // 다섯번 반복
}
console.log('final i:', i); // final i: 5
✍ 그냥 let 선언 방식을 사용하자!
const
선언 방식은?블록 스코프를 따른다.
Lexical scope
렉시컬 스코프
에 의해 함수가 호출된 위치가 아닌 함수가 선언되는 위치에서 변수가 정해진다.
let num = 1;
function a(){
let num = 10;
b()
}
function b(){
console.log(num);
}
a(); // 1
외부 함수의 변수에 접근할 수 있는 내부 함수를 클로저 함수라고 한다.
// 예제) HTML 문자열 생성기
const tagMaket = tag => content => `<${tag}>${content}</${tag}>`
const divMaker = tagMaker('div');
divMaker('hello') // '<div>hello</div>'
const anchorMaker = tagMaker('a');
anchorMaker('go') // '<a>go</a>'
anchorMaker('urclass') // '<a>urclass</a>'
함수의 재사용성을 극대화하여 함수 하나를 완전히 독립적인 부품 형태로 분리하는 것을
모듈화
라고 한다. 즉,클로저는 모듈화에 유리하다.
value
는 직접 수정이 불가능
하다. 하지만, 리턴하는 객체가 제공하는 메서드를 통해 간접적 조작은 가능
하다.// 예제) 재활용 가능한 makeCounter 함수
const counter1 = makeCounter();
counter1.increase();
counter1.increase();
counter1.decrease();
counter1.getValue(); // 1
const counter2 = makeCounter();
counter2.decrease();
counter2.decrease();
counter2.decrease();
counter2.getValue(); // -3
counter1
과 counter2
의 value는 서로에게 영향을 끼치지 않는다.ES6(ECMA Script6)
주요 문법spread
/ rest
문법 IMMUTABLEspread
문법배열을 풀어서 인자로 전달
하거나, 배열을 풀어서 각각의 요소로 넣을때
사용한다.인자
앞에 ...
을 붙인다.function sum(x, y, z) {
return x + y + z;
}
const numbes = [1, 2, 3];
sum(...number) // 6
rest
문법파라미터를 배열의 형태로 받아서 사용
할 수 있다.파라미터의 개수가 가변적일 때 유용
하다.파라미터
앞에 ...
을 붙인다.function sum(...theArgs) {
return theArgs.reduce((prev, curr) => {
return prev + curr;
});
}
sum(1,2,3) // 6
sum(1,2,3,4) // 10
✍️ reduce(콜백함수, 초기값) 메서드
prev
에 누적된다.prev
는 초기값을 제공한 경우에는 초기값이 할당되고, 초기값을 제공하지 않을 경우에는 배열의 첫번째 값이 할당된다.curr
에는 초기값을 제공하지 않을 경우 배열의 두번째 값을 할당하고, 초기값을 제공할 경우 배열의 첫번째 값을 할당한다.let parts = ['shoulders', 'knees'];
let lyrics = ['head', ...parts, 'and', 'toes'];
console.log(lyrics) // ['head', 'shoulders', 'knees', 'and', 'toes']
let arr1 = [0, 1, 2];
let arr2 = [3, 4, 5];
arr1 = [...arr1, ...arr2];
console.log(arr1) // [0, 1, 2, 3, 4, 5]
arr.slice()
와 유사 )let arr = [1, 2, 3];
let arr2 = [...arr]; // arr.slice()와 유사
arr2.push(4); // [1, 2, 3, 4] // arr2를 수정해도 arr은 바뀌지 않는다.
console.log(arr) // [1, 2, 3]
console.log(arr2) // [1, 2, 3, 4]
✍️ 키가 같을 경우 뒤의 값으로 덮어 씌워진다.
그렇지 않을 경우, 각각의 키와 값이 모두 그대로 전달된다.
let obj1 = { foo: 'bar', x: 42 };
let obj2 = { foo: 'baz', y: 13 };
let clonedObj = { ...obj1 };
let mergedObj = { ...obj1, ...obj2 };
console.log(clonedObj) // { foo: 'bar', x: 42 }
console.log(margedObj) // { foo: 'baz', x: 42, y: 13 }
function myFun(a, b, ...manyMoreArgs) {
console.log("a", a);
console.log("b", b);
console.log("manyMoreArgs", manyMoreArgs);
}
myFun("one", "two", "three", "four", "five", "six");
// a one
// b two
// manyMoreArgs ["three", "four", "five", "six"]
구조 분해 할당은
spread
문법을 이용하여 값을 해체한 후, 개별 값을 변수에 새로 할당하는 과정을 말한다.
const [a, b, ...rest] = [10, 20, 30, 40, 50]
console.log(a) // 10
console.log(b) // 20
console.log(rest) // [30, 40, 50]
const {a, b, ...rest} = {a: 10, b: 20, c: 30, d: 40}
console.log(a) // 10
console.log(b) // 20
console.log(rest) // {c: 30, d: 40}
// 예제) 함수에서 객체 분해
function whois({
displayName: displayName,
fullName: {firstName: name}
}){
console.log(displayName + " is " + name);
}
let user = {
id: 42,
displayName: "jdoe",
fullName: {
firstName: "John",
lastName: "Doe"
}
};
whois(user) // jdoe is John