**코언즈는 불교에서 유래된 단어로,
결론을 내리기 전에 이게 왜 맞는지
깊게 고민한다는 의미를 가지고 있다고 합니다.
**답이 미리 제시되어 있기 때문에 고민 없이 풀면,
큰 어려움 없이 전부 다 풀 수 있습니다.
하지만 그게 왜 정답인지 깊게 고민해 보는 시간을 갖지 않는다면 충분히 성장하기 어려울 것입니다.
Koans 문제 중에는 학습하지 않은 개념도 의도적으로 포함되어 있습니다. 페어와 함께 깊게 고민하고, 정답을 설명할 수 있도록 연습해 보세요.
코딩 공부에서는 항상 회고하고, 고민하기를 권유한다.
본인이 모든 것을 다 알고 있다고 생각하는 것을 방지하기 위함인 것도 있는것 같고.
의도적으로 코드의 작동원리들에 대해
이해하게 만들기 위함인 것도 있는 것 같다.
그리고 아주 쉬운 개념도 말로 표현하고
상대에게 설명해주면서 나 스스로 이해되는 측면도 있는 것 같다.
그냥 글로 설명되어 있는 내용을
나의 언어로 만들어서 정리해야 진짜 공부가 되는 것 같다.
페어분들이 학습하는 방법이나, 사고하는 방식을 배우며
코딩을 학습하는 법에 대해 익힐 수 있었다.
(스코프)는 자바스크립트 뿐만 아니라 모든 프로그래밍 언어에서 가장 기본적인 개념의 하나로 반드시 알고 넘어가야한다. 하지만, 자바스크립트의 유효범위는 다른 언어의 유효범위와 다르다고 한다.
유효범위의 종류에는 크게 두 가지가 있다.
전역 스코프 (Global scope) : 스크립트 전체에서 참조되는 것을 의미하며, 어느 곳에서든 참조 된다.
지역 스코프 (Local scope) : 정의된 함수 내에서만 참조되는 것을 의미하며, 밖에서는 참조 되지 않는다.
유효범위의 특징을 크게 나열하면 다음과 같다.
함수 단위의 유효범위(function-level-scope)
변수명 중복 허용
암묵적 선언(implied globals)
Lexical scoping(Static scoping)
1-1. function-level scope
function-level scope란 함수 코드 블럭 내에서 선언된 변수는 함수 코드 블럭 내에서만 유효하고 함수 외부에서는 유효하지 않다는 것이다.
(ES6 이후, let 키워드를 쓰면 block-level scope를 사용할 수 있다.)
var x = 0;
{
var x = 1;
console.log(x); // 1
}
console.log(x); // 1
let y = 0;
{
let y = 1;
console.log(y); // 1
}
console.log(y); // 0
1-2. 변수명 중복 허용
글로벌 영역에 변수를 선언하면 이 변수는 어느 곳에서든지
참조할 수 있는 global scope를 갖는 전역 변수가 된다.
var global = 'global';
function foo() {
var local = 'local';
console.log(global); // global
console.log(local); // local
}
foo();
console.log(global); // global
console.log(local); // Uncaught ReferenceError: local is not defined
1-3. 암묵적 전역 (implied globals)
명시적으로 변수 앞에 var를 붙여주지 않으면 암묵적 전역변수가 된다.
function foo() {
x = 1; // Throws a ReferenceError in "use strict" mode
var y = 2;
}
foo();
console.log(x); // 1
console.log(y); // ReferenceError: y is not defined
1-4. Lexical scoping (Static scoping)
자바스크립트는 함수가 선언된 시점에서의 유효범위를 갖는다.
예제1
var number = 1234
function printNumber() {
console.log(number);
}
function wrapper() {
number = 4321
printNumber();
}
wrapper(); // 4321
printNumber함수를 실행하기 직전에 number의 값을 변경 해주었으므로 wrapper함수를 실행 시켰을 때에 값이 변경되었다.
예제2
var number = 1234
function printNumber() {
console.log(number);
}
function wrapper() {
var number = 4321
printNumber();
}
wrapper(); //1234
wrapper함수 안에서 var키워드를 사용하자 결과가 달라진다.
함수를 처음 선언하는 순간, 함수 내부의 변수는 자기 스코프로부터 가장 가까운 곳(상위 범위에서)에 있는 변수를 계속 참조하게 된다.
위의 예시에서는 printNumber 함수 안의 number 변수는 선언 시 가장 가까운 전역변수 number를 참조하게 된다.
그래서 wrapper 안에서 printNumber 호출해도 지역변수 number을 참조하는 게 아니라 그대로 전역변수 number 값인 1234가 나오는 것이다.
새롭게 정의된 스코프는 상위의 스코프에 접근할 수 있다.
스코프 체인은 scope의 가장 내부에서 scope chain을 따라 바깥쪽으로 검색을 하게 된다.
함수 안의 함수
// counter는 outer 함수
// changeCount는 inner함수
// 객체를 리턴하고 있고 객체 안에는 increase, decrease, show와 같은 inner함수들을 저장
const counter = function() {
let count = 0;
function changeCount(number) {
count += number;
}
return {
increase: function() {
changeCount(1);
},
decrease: function() {
changeCount(-1);
},
show: function() {
alert(count);
}
}
};
// counter를 실행하면 outer함수 스코프를 기억하고 있는 클로저들이 담긴 객체를 반환
// counterClosure는 counter함수 내부에 정의된 count나 changeCount에 접근 가능
const counterClosure = counter();
counterClosure.increase(); //
counterClosure.show(); // 1
counterClosure.decrease();
counterClosure.show(); // 0
개인적으로 생활코딩에서 설명하는 클로저가 가장 이해하기 좋았다.
내부함수는 외부함수의 지역변수에 접근 할 수 있는데 외부함수의 실행이 끝나서 외부함수가 소멸된 이후에도 내부함수가 외부함수의 변수에 접근 할 수 있다.
이러한 메커니즘을 클로저라고 한다
++ 내부함수에서 외부함수에서 선언된 변수를 사용한다면 그 내부함수는 클로저이다.