[ JavaScript ] 객체에 대한 모든 것 (2)

·2023년 8월 3일

JavaScript

목록 보기
6/9
post-thumbnail

📌 Scope

var num1 = 20;
function levelOne() {
    console.log(num1);
}
levelOne();

// result > 40

  • 가장 가까운 scope 에 있는 변수를 가져오기 때문에 40이 출력됨
function levelOne() {
    var num1 = 40;

    console.log(num1);
}
levelOne();

// result > 40

  • 함수 scope 안에서 num 을 선언해도 상위 함수의 변수 num 을 덮진 않음
console.log(num1);

// result > 20

  • 모든 선언은 가장 가까운 scope 에 있는 선언부터 활용
function levelOne() {
    var num1 = 40;

    function levelTwo() {
        var num2 = 99;

        console.log(`levelTwo num2 : ${num2}`);
        
        // 바로 상위 scope 에있는 num1 출력 (20이 아닌 40 출력)
        console.log(`levelTwo num1 " ${num1}`);     
    }

    levelTwo();
    
    // 현재 함수 scope 에있는 num1 출력 (20이 아닌 40 출력)
    // => 모든 선언은 가장 가까운 scope 에 있는 선언부터 활용
    console.log(`levelOne num1 : ${num1}`);
}
levelOne();
console.log(num1);		// result > 20
console.log(num2);		// ReferenceError: num2 is not defined


🧷 Lexical Scope

: 선언된 위치가 상위 스코프를 정함
Dynamic scope : 실행한 위치가 상위 스코프 결정
JS 는 lexical scope를 사용하기 때문에 함수의 상위 스코프가 정의 시점에 평가

var num3 = 3;

function functionOne() {
    var num3 = 100;

    funtionTwo();
}

function funtionTwo() {
    console.log(num3);
}
functionOne();  

functionOne 에서 실행했으니까 100을 가져올 것인가?
global scope에 있는 3을 가져올 것인가?
=> global scope 에서 값 가져옴

result : 3


  • for문, if문 등은 새로운 scope를 만들지 않음
    => 기존의 i가 global scope 로 변경됨
    => var 키워드 로 선언시 scope 가 생기는 것은 함수일 때만
var i = 999;
for (var i = 0; i < 10; i++) {
    console.log(i);
}
console.log(`i in global scope : ${i}`);


  • let, const 키워드 사용시
    => 함수뿐만 아니라 조건/순환문에서 block level scope 를 만듦
i = 999;
for (let i = 0; i < 10; i++) {
    console.log(i);
}
console.log(`i in global scope : ${i}`);


💡 요약
var 키워드함수 레벨 스코프만 만듦
let, const 키워드함수 레벨 스코프블록 레벨 스코프를 만들어냄



📌 this

  • this 키워드는 바인딩 객체가 생성되는 시점에 결정됨
  • 일반 함수 실행시 this 키워드가 global object 에 매핑됨
const testFinction = function () {
    return this;
}
console.log(testFinction());


const yujin = {
    name: '안유진',
    year: 2003,
    sayHello: function () {
        return `안녕하세요 저는 ${this.name}입니다!`;
    }
}
console.log(yujin.sayHello());


function Person(name, year) {
    this.name = name;
    this.year = year;

    this.sayHello = function () {
        return `안녕하세요 저는 ${this.name}입니다!!`;
    }
}
const yujin2 = new Person('안유진', 2003);
console.log(yujin2.sayHello());


  • 가장 상위 게벨의 함수 선언시 this 가 실행하는 객체로 자동으로 매핑됨
Person.prototype.dance = function () {
    return `${this.name}이 춤을 춘당`;
}
console.log(yujin2.dance());


  • 그 외의 위치에서 함수 선언시, 함수의 객체는 무조건 global
Person.prototype.dance = function () {
    function dance2() {
        return `${this.name}이 춤을 춘당`;
    }
    return dance2();
}
console.log(yujin2.dance());


💡 this 키워드가 어떤 걸 가르키냐는 세가지만 기억할 것!!
1. 일반 함수가 호출할 땐 this가 최상위 객체 (global 또는 window)를 가리킴
2. 메서드로 호출할 때 호출도니 객체를 가리킴
3. new 키워드를 사용해 객체를 생성했을 때 객체를 가리킴
=> 2, 3이 아닌 경우 1임

💡 this원하는 값으로 매핑하는 방법
1. call()
2. apply()
3. bind()


function returnName() {
    return this.name;
}
console.log(returnName());


🔎 call(), apply()

const yujin3 = {
    name: '안유진'
}
console.log(returnName.call(yujin3));
console.log(returnName.apply(yujin3));


👩‍💻 call()apply()의 차이는 무엇인가?
call() -> 콤마를 기반으로 argument 를 순서대로 넘겨줌
apply() -> argument 를 리스트로 입력해야함
공통점 ) 실행하는 순간 바로 계산

function multiply(x, y, z) {
    return `${this.name} / 결과값 : ${x * y * z}`;
};
console.log(multiply.call(yujin3, 3, 4, 5));
console.log(multiply.apply(yujin3, [3, 4, 5]))


🔎 bind()

  • this 바인딩 한 후, 나중에 실행가능
const lateFunc = multiply.bind(yujin3, 3, 4, 5);
console.log(lateFunc);
console.log(lateFunc());



📌 Execution Context

  • 실행하려는 JS 코드와 코드를 실행할 때 필요한 정보를 담고있는 특수한 환경. 코드 실행에 필요한 모든 데이터들을 들고 있는 환경이라고 생각

Execution Context 크게 두 개로 나뉨
1. Global context
: 최상위 Execution Context
코드 실행시 무조건 생성되는 context로 웹에서의 window 객체나 nodeJS 에서의 global 객체를 생성하고 들고있음
2. Function Context
: 함수가 실행될 때마다 함수별로 실행되는 context.
함수 실행에 대한 모든 정보를 갖고 있음


  • JS 는 single thread 로 실행된
  • single thread 안에는 하나의 Memory Heap 과 하나의 Call Stack 존재


🔎 Execution Context Stack 작동과정

  • Creation Phase
    - Global Object 생성. window 또는 global 객체가 생성되고 함수에서는 arguments 객체가 생성됨
    - this 를 window 또는 global 에 바인딩함
    - 변수와 함수를 Memory Heap에 배정하고 기본 값을 undefined 로 저장

  • Execution Phase
    - 코드를 실행
    - 필요하면 새로운 Execution Context 생성



📌 Closure

  • 어떤 함수와 해당 함수가 선언된 렉시컬 환경의 조합
    => 상위 함수보다 하위 함수가 더 오래 살아있는 경우
function getNumber() {
    var number = 5;

    function innerGetNumber() {
        return number;
    }

    return innerGetNumber;
}
const runner = getNumber();
console.log(runner);
console.log(runner());


👩‍💻 어떤 점이 유용 ?

  1. 데이터 캐싱
function cacheFuntion(numNumb) {
    // 아래 계산은 매우 오래걸린다는 가정을 했을 때
    // 반복적으로 계속 작업해야함 => 비표율적
    var number = 10 * 10

    function innercarhceFunction(newNumb) {
        return number * number;
    }

    return innercarhceFunction;
}

const runner2 = cacheFuntion();
console.log(runner2(10));

  • 반복적으로 특정값을 변환해야할 때
function cacheFuntion2() {
    var number = 99;

    function increment() {
        number++;
        return number;
    }
    return increment;
}

const runner3 = cacheFuntion2();
console.log(runner3());
console.log(runner3());


  1. 정보 은닉
function Idol(name, year) {
    this.name = name;

    var _year = year;
    this.sayNameAndYear = function () {
        return `안녕하세요. 저는 ${this.name} 입니다. ${_year} 년에 태어났습니다.`
    }
}

const yujin = new Idol('안유진', 2003);
console.log(yujin.sayNameAndYear());

console.log(yujin.name);
console.log(yujin._year);





📒 코드팩토리 - <9시간만에 끝내는 코드팩토리의 Javascript>

0개의 댓글