[ydkjsy]Scope & Closures-3-The Scope Chain

lexical scope란? 코드에 작성한 것을 기준으로 즉, 어디에 선언되었는지를 기준으로 scope를 지정한 것을 말한다. 알면 좋은 점 실수를 줄이고 활용하여 사용 가능하다?

스코프 체인은 다른 스코프들 안에서 중첩된 스코프 간의 연결을 말한다.

"Lookup" Is (Mostly) Conceptual

현재 파일에서 선언되지 않는 변수를 참조한다면, 런타임의 다른 파일이 실제로 공유된 글로벌 스코프에 해당 변수를 선언할 수 있으므로 무조건 에러는 아니다.
결국, 접근 가능한 버킷에서 적절하게 선언되었는지는 런타임까지 봐야한다.
처음에 선언되지 않은 변수에 대한 참조는 해당 파일 컴파일시, 다른 관련된 파일이 컴파일되거나, 런타임 개시 때까지 색이 지정되지 않고 글로벌 스코프에서 체크하게 된다.
이 조회는 변수당 최대 한번만 필요하다. 런타임 동안 마블 색을 변경할 수 없기 때문에.

Shadowing

보통 같은 스코프에 같은 이름을 쓰지 않지.

var studentName = "Suzy";

function printStudent(studentName) {
    studentName = studentName.toUpperCase();
    console.log(studentName);
}//lookup의 방식을 떠올려라.

printStudent("Frank");
// FRANK

printStudent(studentName);
// SUZY

console.log(studentName);
// Suzy

여기서 함수의 parameter studentName로 인해 전역에 있는 studentNameshadow 되어 함수 내부에서 사용 불가능.

Global Unshadowing Trick

쓰지마. 글로벌 객체window의 property를 이용하여 불러온다.

var studentName = "Suzy";

function printStudent(studentName) {
    console.log(studentName);
    console.log(window.studentName);
}

printStudent("Frank");
// "Frank"
// "Suzy"

실제 변수에 접근하는 getter/setter로 생각할 수 있는데, 사실 글로벌 객체에 property를 정하고 생성해서 전역 변수 만들 수도 있는데, 이 방법은 몇가지 제한이 있다. 전역변수일 때, var 나 function으로 선언되었을 때.

var one = 1;
let notOne = 2;
const notTwo = 3;
class notThree {}

console.log(window.one);       // 1
console.log(window.notOne);    // undefined
console.log(window.notTwo);    // undefined
console.log(window.notThree);  // undefined
var special = 42;

function lookingFor(special) {
    // The identifier `special` (parameter) in this
    // scope is shadowed inside keepLooking(), and
    // is thus inaccessible from that scope.

    function keepLooking() {
        var special = 3.141592;
        console.log(special);
        console.log(window.special);
    }

    keepLooking();
}

lookingFor(112358132134);
// 3.141592
// 42

Copying Is Not Accessing

var special = 42;

function lookingFor(special) {
    var another = {
        special: special
    };

    function keepLooking() {
        var special = 3.141592;
        console.log(special);
        console.log(another.special);  // Ooo, tricky!
        console.log(window.special);
    }

    keepLooking();
}

lookingFor(112358132134);
// 3.141592
// 112358132134
// 42

Illegal Shadowing

let은 var를 shadow 가능, 반대는 var가 함수 내부에 있는 것 아니면 에러.

function something() {
    var special = "JavaScript";
    {
        let special = 42;   // totally fine shadowing
        // ..
    }
}
function another() {
    // ..
    {
        let special = "JavaScript";
        {
            var special = "JavaScript";
            // ^^^ Syntax Error cross the boundary
        }
    }
}

Function Name Scope

함수 표현식에서 함수 자체는 호이스팅되지 않는다.
여기서 ofTheTeacher는 함수 내부의 식별자로 선언된다.(사실은 함수 스코프는 아님)

var askQuestion = function ofTheTeacher() {
    console.log(ofTheTeacher);
};

askQuestion();
// function ofTheTeacher()...

console.log(ofTheTeacher);
// ReferenceError: ofTheTeacher is not defined

엄격모드에서는 이 식별자에 재할당할 경우 TypeError.비엄격모드도 자동으로 실패.
익명 함수일 경우에는 두 범위에 영향을 주는 이름 식별자가 없다.

Arrow Functions

어휘적으로 익명이다. 추론될 뿐. 다음은 여러 유형.

() => 42;

id => id.toUpperCase();

(id,name) => ({ id, name });

(...args) => {
    return args[args.length - 1];
};

일반 함수와 같은 렉시컬 스코프를 가진다.

좋은 웹페이지 즐겨찾기