본문 바로가기
언어 정리/JavaScript

렉시컬 환경, 정적 바인딩, 동적 바인딩, 화살표 함수 정리

by 알 수 없는 사용자 2024. 9. 1.

정리

키워드 : 정적바인딩, 동적바인딩, 렉시컬 환경, 상위 객체, 객체리터

               함수 선언식, 함수 선언식, 화살표 함수

'use strict';

// class SimpleDeclareClass {
//     constructor(name) { this.name = name; }
//     sayHi() { alert(this.name); }
// }

// let SimpleExpressClass = class {
//     sayHi() {
//         alert("안녕하세요.");
//     }
// };


// function makeClass(phrase) {
//     // 클래스를 선언하고 이를 반환함
//     return class {
//         sayHi() {
//             alert(phrase);
//         };
//     };
// }

// // 새로운 클래스를 만듦
// let User1 = makeClass("안녕하세요.");

// new User1().sayHi(); // 안녕하세요.



// class User {

//     constructor(name) {
//         // setter를 활성화합니다.
//         this.name = name;
//     }
//     /**
//      * 참고로 getter와 setter는 User.prototype에 정의됩니다.
//      */
//     get name() {
//         return this._name;
//     }

//     set name(value) {
//         if (value.length < 1) {
//             alert("이름이 너무 짧습니다.");
//             return;
//         }
//         this._name = value;
//     }
// }

// let user = new User("보라");
// alert(user.name); // 보라
// user.name = "디노";
// alert(user.name);

// let testConst = new User(""); // 이름이 너무 짧습니다.


/**
 * This 함수와 Object, Class 
 * 함수 표현식, 함수 선언식, 화살표 함수
 * 이해하기

 * 화살표 함수는 정적 바인딩으로 this의 참조를 고정적으로 가져가며, this 가 선언된 스코프( { } )의 상위객체를 참조 하게 된다.
 * 이를 렉시컬 환경(스코프)라고 부른다.
 * 렉시컬 환경 정의 : "코드가 작성된 위치에 따라 변수와 상위 스코프를 결정하는 JS의 스코프 체계이다."
 * ex) 예를 들면
       \ 전역 스코프에서 정의된 경우: 전역 스코프에서 화살표 함수를 정의하면, 그 this는 전역 객체(window 또는 global)를 참조합니다.
       \ 객체의 메서드로 정의된 경우: 객체의 메서드로 화살표 함수를 정의하면, 그 this는 해당 객체가 아닌, 그 객체가 정의된 상위 스코프의 this를 참조합니다.
       \ 클래스 내부에서 정의된 경우: 클래스 내부에서 화살표 함수를 정의하면, 그 this는 클래스 인스턴스를 참조합니다. 
       \                             이는 클래스의 메서드가 인스턴스의 컨텍스트에서 호출되기 때문입니다.
 */

let buttonFuncObj = {
    value1 : "buttonFuncObj !",

    // 함수 선언 : 코드가 실행되기 전에 메모리에 로드
    clickDeclare() {
        alert(this.value1);  // buttonFuncObj !
    },

    // 함수표현식 : 런타임 중에 로딩
    clickExpress : function () {
        alert(this.value1);  // buttonFuncObj !
    },

    // 화살표 함수 : 런타임 중에 로딩 + 렉시컬 스코프 적용
    // 렉시컬 환경 : 현재 {} 스코프 상위의 this 를 정적 바인딩한다. -> 어느 상황이든 동일한 this를 지칭 하게 해줌
    clickArrow : () => {
        alert(this.value1);  // undefined
    }
}

// 함수 선언식: 정의된 지점의 this (동적 바인딩)
buttonFuncObj.clickDeclare();  // buttonFuncObj !
// 함수 표현식: 정의된 지점의 this (동적 바인딩 )
buttonFuncObj.clickExpress();  // buttonFuncObj !

// 화살표 함수: 작성된 위치의 상위객체를 고정적으로 참조 this  (정적 바인딩 )
buttonFuncObj.clickArrow();    // undefined
// 아래의 코드랑 동일한거임
alert(this.value1);            // undefined
/**
 * 화살표 함수만 제대로 안나오는 이유 :
 * 함수에서 사용되는 중괄호"{ }"는 독립적인 스코프를 제공하지만, 
 * 객체 리터럴의 중괄호"{ }"는 단순히 키-값 쌍의 집합이기 때문에 "buttonFuncObj.clickArrow()"함수의 상위 함수는 전역객체가 된다.
 * 따라서 전역객체에 value1은 없으므로 "undefined"가 출력된다.
 * 
 * 객체 리터럴 정의 : 중괄호 {}를 사용하여 키-값 쌍의 집합을 정의하는 자바스크립트의 문법
 */


// --------------------------------------------------------------------------------------------------------------------

class Button {
    constructor(value) {
        this.value = value;
    }

    // 함수 선언식
    clickDeclare() {
        alert(this.value);
    }

    // 함수표현식
    clickExpress = function () {
        alert(this.value);
    }

    // 화살표 함수
    clickArrow = () => {
        alert(this.value);
    }
}

let button = new Button("안녕하세요.");

// 함수 선언식: 정의된 지점의 this (동적 바인딩)
button.clickDeclare();  // "안녕하세요."
// 함수 선언식: 정의된 지점의 this (동적 바인딩)
button.clickExpress();  // "안녕하세요."
// 화살표 함수: 작성된 위치의 상위객체를 고정적으로 참조 this  (정적 바인딩 )
button.clickArrow();    // "안녕하세요."

// setTimeout() 함수 설명 : 
// setTimeout(callback, 1000)의 콜백 함수는 기본적으로 전역 컨텍스트에서 호출

// 함수 선언식: 정의된 지점의 this (동적 바인딩)
setTimeout(button.clickDeclare, 500);  // undefined
// 함수 선언식: 정의된 지점의 this (동적 바인딩)
setTimeout(button.clickExpress, 1000); // undefined

// 화살표 함수: 작성된 위치의 상위객체를 고정적으로 참조 this  (정적 바인딩 )
setTimeout(button.clickArrow, 1500);   // "안녕하세요."
/**
 * 화살표 함수만 제대로 나오는 이유 : 
 * callback 등록시 해당 함수부분만 전달되므로 전역 컨텍스트에서 호출하게 된다. 그래서 함수 선언식,표현식 둘다 button을 this로 가리키지 못함
 * 그러나 화살표 함수의 경우 정적 바인딩이므로 고정적으로 this 의 타겟을 참조 할 수 있음
 * 또한 렉시컬 환경이 적용되므로 상위 객체를 this로 참조 하게 된다. [ 상위 객체를 this로 참조란 >> { }스코프 상위의 존재를 의미함 ]
 * 따라서 화살표 함수에서의 this 는 상위객체인 button 인스턴스를 가리키게 되므로 어디서든 button인스턴스를 this로 가리킬 수 있다.
 */

댓글