원시 자료형: 객체가 아니면서 method를 가지지 않는 6가지의 타입
참조 자료형
let first = [10, 20, 30, 40];
let second = first;
second[0] = 5;
fisrt // [5, 20, 30, 40]
fisrt[2] = 55;
second // [5, 20, 55, 40]
→ first의 0번째 인덱스에 있는 요소 = 5
→ first와 second는 같은 주소를 공유
→ 주소를 공유하고 있어서 second의 값을 변경하면 first의 값도 같이 변경된다.
참조 자료형의 ===
: 주소값이 같은지 확인
console.log([1,2,3] === [1,2,3])
→ false
let x = { foo: 3};
let y = x;
y = 2;
// x.foo = 3
let myArr = [2, 3, 4, 5];
let ourArr = myArr;
ourArr[2] = 25; // -> myArr: [2, 3, 25, 5]
ourArr = undefined; // myArr에 접근 불가능
let score = 80;
function doStuff(value){
value = 90;
}
doStuff(score)
score: 80
→ 매개변수 value에 score 값 80이 전달되고 value=90
에서 value에 90 할당
→ 변수 score의 값 80은, 참조 자료형이 아니라서 주소값 전달X
→ 초기 할당값 80 그대로 유지됨.
: 변수 접근 규칙에 따른 유효 범위
let username = 'kimcoding';
if (username) {
let message = `Hello, ${username}!`;
console.log(message); // Hello, kimcoding!
}
console.log(message); // ReferenceError
→ message 변수 자체가 중괄호 안쪽에 선언되어 있어서 바깥쪽에서 접근X
let name = '김코딩'; // 전역변수
function showName(){
let name = '박해커'; // 지역변수
}
function Name(){
name = '박해커';
}
console.log(name); // 김코딩
showName(); // 박해커
console.log(name); // 김코딩
Name(); // 박해커
console.log(name) // 박해커
스코프의 종류
for (let i = 0; i < 5; i++){
console.log(i); // 0 1 2 3 4
}
console.log("final i:", i); // reference error
for (var i = 0; i < 5; i++){
console.log(i); // 0 1 2 3 4
}
console.log("final i:", i); // 5
→ var 키워드는 for문이 만들어낸 블록 스코프 무시
블록 스코프 따름
값의 변경을 최소화하여 안전한 프로그램 만들기 가능
값을 새롭게 할당하지 않으면 const 사용 권장됨
값을 재할당하면 TypeError 발생
let | const | var | |
---|---|---|---|
유효 범위 | 블록 스코프 |
및
함수 스코프 | 블록 스코프
및
함수 스코프 | 함수 스코프 |
| 값 재할당 | 가능 | 불가능 | 가능 |
| 재선언 | 불가능 | 불가능 | 가능 |
var 키워드 사용시
let 키워드 사용시
greeting 변수 안보임
window 객체(브라우저 only)
전역변수는 최소화하기
let, const 주로 사용하기
선언 없는 변수 할당 금지
function showAge(){
// age를 전역변수로 취급
age = 90;
console.log(age); // 90
}
showAge();
console.log(age); // 90
console.log(window.age); // 90
→ age는 선언한적이 없지만 값을 할당하면서 마치 var로 선언된 전역변수처럼 작동
'use strict';
→ 브라우저가 보다 엄격하게 작동하도록 만들어줌
A closure is the combination of a function and the lexical environment within which that function was declared. This environment consists of any local variables that were in-scope at the time the closure was created.
클로저는 함수와 함수가 선언된 어휘적 환경의 조합을 말한다.
이 환경은 클로저가 생성된 시점의 유효 범위 내에 있는 모든 지역 변수로 구성된다.
클로저 함수
const add = (x, y) => x + y;
add(5, 7); // 12
const adder = x => y => x + y;
adder(5)(7); // 12
→ 함수의 호출(invocation) 두 번 발생
typeof adder(5) // 'function'
adder(5) // y => x + y
→ adder(5)
의 리턴값이 함수의 형태
→ adder
는 함수를 리턴하는 함수
const adder = function (x) {
return ***function (y) {
return x+ y;
}***
}
→ 클로저 함수는 위 코드와 비슷한 모양
x
가 선언된 함수는 바깥쪽에 있으니 ‘외부 함수’y
가 선언된 함수는 안쪽에 있으니 ‘내부 함수’Q. 외부 함수는 y
에 접근 가능??
→ X. 바깥 스코프에서 안쪽 스코프로의 접근은 불가능
Q. 내부 함수는 x에 접근 가능??
→ O. 안쪽 스코프는 바깥 스코프에서 선언된 변수에 접근 가능
클로저 함수
외부 함수(adder)의 실행이 끝나더라도, 외부 함수 내 변수 x
사용O
외부 함수 내 변수가 메모리 상에 저장
const adder = function (x) {
return function (y) {
return x + y;
}
}
const add5 = adder(5); // 함수 실행이 끝나도 5 값 사용 가능
add5(7) // 12 -> y에다가 7 넣기
add5(10) // 15 -> y에다가 10 넣기
특정 데이터를 스코프 안에 가두어 둔 채로 계속 사용 가능
const tagMaker = tag => content => `<${tag}>${content}</${tag}>`
const divMaker = tagMaker('div');
divMaker('Hello') // '<div>hello</div>'
divMaker('World') // '<div>World</div>'
const anchorMaker = tagMaker('a');
anchorMaker('go') // '<a>go</a>'
anchorMaker('urclass') // '<a>urclass</a>'
클로저를 이용해 내부 함수를 단 하나만 리턴하지 않고, 객체에 담아 여러 개의 내부 함수를 리턴하도록 만든다.
const makeCounter = () => {
let value = 0;
return {
increase: () => {
value = value + 1
},
decrease: () => {
value = value - 1
},
getValue: () => value
}
}
const counter1 = makeCounter();
counter1 // { increase: f, decrease: f, getValue: f }
→ makeCounter 함수는 increase, decrease, getValue 메서드를 포함한 객체 하나를 리턴.
→ counter1 은 객체 (함수 여러개를 포함한)
Q. makeCounter 함수를 바꾸지 않고, value라는 변수에 값을 새롭게 할당할 수 있는 방법은?
A. X: 외부 스코프에서는 내부 스코프의 변수에 접근할 수 없으므로 불가능
대신, 리턴하는 객체가 제공하는 메서드를 통해 ‘value’ 값을 간접적으로 조작 가능.
⇒ 정보의 접근 제한(캡슐화). 스코프로 value값을 보존. 전역변수X
재활용이 가능한 makeCounter 함수
여러 개의 counter를 만드는 것이 가능
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에서의 value와 counter2 에서의 value는 서로에게 영향X
→ 각각의 값을 보존