상세 컨텐츠

본문 제목

[TIL] 2024.01.02 this바인딩

[TIL]

by 재호링 2024. 1. 2. 22:52

본문

오늘은 3주차 강의에서 배운 내용을 다루려고한다.

 

1. 얕은 복사와 깊은 복사

객체가 중첩되어 사용되었을때 얕은복사를 사용하게되면 바로 아래 단계의 값만 복사되어서

제대로된 복사가 실행되지 않는다.

 

이를 해결하기 위해 나온 것이 '깊은 복사'

깊은복사는 내부 스코프에 있는 모든 값을 하나하나 다 적용해 복사하는 방법이다.

 


var user = {
    name: 'wonjang',
    urls: {
        portfolio: 'http://github.com/abc',
        blog: 'http://blog.com',
        facebook: 'http://facebook.com/abc',
    }
};

var user2 = copyObject(user);

user2.name = 'twojang';

// 바로 아래 단계에 대해서는 불변성을 유지하기 때문에 값이 달라지죠.
console.log(user.name === user2.name); // false

// 더 깊은 단계에 대해서는 불변성을 유지하지 못하기 때문에 값이 같아요.
// 더 혼란스러워 지는거죠 ㅠㅠ
user.urls.portfolio = 'http://portfolio.com';
console.log(user.urls.portfolio === user2.urls.portfolio); // true

// 아래 예도 똑같아요.
user2.urls.blog = '';
console.log(user.urls.blog === user2.urls.blog); // true


 

위 코드를 해결하려면 재귀적 수행이 필요하다. 즉 자기 자신의 호출을 반복하여 실행하는 것을 말하는데

이를 해결하기 위해 for ~ in을 활용한다.(재귀적 수행을 for ~ in이 해준다는 것이다.)

 



var copyObjectDeep = function(target) {
    var result = {};
    if (typeof target === 'object' && target !== null) {
        for (var prop in target) {
            result[prop] = copyObjectDeep(target[prop]);
        }
    } else {
        result = target;
    }
    return result;
}

 

타겟의 타입이 오브젝트이거나 널 값이 아니면 프로퍼티 즉 자신의 호출을 반복한다는 의미이다.

 

2. 실행컨텍스트

실행컨텍스트는 코드의 실행순서는 어떻게 되는 것인가에 대한 고찰이었다.

실행컨텍스트가 활성화되는 시점엔 어떤 일이 일어날까라는 관점에선 재밌게 들었다.

먼저 콜 스택에 쌓아 올린다는 개념이였는데, 먼저 전역이 들어오고 그 다음 스코프에 쌓인 객체, 다음 스코프에

쌓인 객체로 이해를했다.

 

// ---- 1번
var a = 1;
function outer() {
    function inner() {
        console.log(a); //undefined
        var a = 3;
    }
    inner(); // ---- 2번
    console.log(a);
}
outer(); // ---- 3번
console.log(a);
 

 

위 코드로 예를 들자면 전역에 있는 a=1이 들어오게 된다. 그 위에 outer()가 쌓이고, inner()가 쌓였다가 사라지게 되고

다시 outer()를 만나고 outer()가 사라지게되고 전역이 실행되어 코드가 종료되는 순서이다.

 

실행 컨텍스트에 담기는 정보는 VE( VariableEnvironment ), LE( LexicalEnvironment ) 둘이 있는데 이 둘은 각각

record( 식별자 ), outer( 외부환경정보 )를 갖고있다. 베리어블과 렉시컬의 차이는 실기간으로 반영을 하냐 안하냐의 차이라고 이해하면된다.

 

3. this의 정의, 바인딩

this. 처음에는 쉽게 이해를 했다. 잠깐 코드를 뜯어 살펴보면 this가 웬만해선 다 박혀있어서 이게 이 객체를 가르키는 구나 정도까지. 근데 역시나 깊이 있게 공부를 하다보면 어렵게 다가와진다. 상항별로 어떻게 달라지는지, 그 이유가 뭔지에 대해 분석하는데 복습이 많이 필요할 것 같다.

 

  • 함수를 호출할 때 사용하는 this. 호출하는 방법에 따라 전역 혹은 지역에서 가리키는 객체가 달라진다.
  • 함수는 독립적인 기능을 수행하는 놈이지만 메서드는 자신을 호출한 객체에 대한 동작을 수행한다.
  • 독립적인 수행 즉 함수로서 호출 할 때의 this는 무조건 전역객체로써 인식하게된다.
  • 메서드에서의 this는 해당 함수를 호출하는 구문 앞에 . or [] 표기가 있는지 확인하면 편하다.
var obj = {
    method: function (x) { console.log(this, x) }
};
obj.method(1); // { method: f } 1
obj['method'](2); // { method: f } 2
 

 


var obj = {
    methodA: function () { console.log(this) },
    inner: {
        methodB: function() { console.log(this) },
    }
};

obj.methodA();             // this === obj
obj['methodA']();          // this === obj

obj.inner.methodB();       // this === obj.inner
obj.inner['methodB']();    // this === obj.inner
obj['inner'].methodB();    // this === obj.inner
obj['inner']['methodB'](); // this === obj.inner
 
  • 실행 컨텍스트가 활성화 될 때 this가 지정되지 않으면 this는 전역 객체를 의미하게 된다는 것을 알 수 있다.

오늘 어려웠던 부분.


var user = {
    name: "john",
    age: 20,
}

var getAged = function (user, passedTime) {
        // 여기를 작성해 주세요!
}


var agedUser = getAged(user, 6);

var agedUserMustBeDifferentFromUser = function (user1, user2) {
    if (!user2) {
            console.log("Failed! user2 doesn't exist!");
      } else if (user1 !== user2) {
        console.log("Passed! If you become older, you will be different from you in the past!")
    } else {
        console.log("Failed! User same with past one");
    }
}

agedUserMustBeDifferentFromUser(user, agedUser);
 

 

3주차 첫 숙제로 제시 된 문제다.

" 가장 아래의 코드가 실행 되었을 때, “Passed ~” 가 출력되도록 getAge 함수를 채워주세요 "

이제는 알게 되어 짐작이 가지만 처음 봤을 때 뉴비인 내가 이걸 직접 작성하라고? 덜컥 심장부터 아팠다.

하지만 모르는걸 가만히 뚫어져라 쳐다볼 수만은 없기에 적절하게 해석영상을 참고하여 풀이해보았다.

agedUser() 함수내에 (user, 6)의 내용을 보았을 때 getAged(user, passedTime) 중 user는 객체가 들어오고

passedTime에 6이 들어간다는 걸 짐작 할 수 있었다. user 객체 안에 age 20 에 6을 더하라는 소리를 인지하고

생성자를 새로 만들고 passedTime을 더 해 문제를 풀이하는 방식이었다. 먼저 가볍게 생각해봤을때,

 
var user = {
    name: "john",
    age: 20,
}

var getAged = function (user, passedTime) {
        // 여기를 작성해 주세요!
    var newUser = user;
    newUser.age += passedTime;

    return newUser;
};


var agedUser = getAged(user, 6);

var agedUserMustBeDifferentFromUser = function (user1, user2) {

    console.log(user1);
    console.log(user2);
   
    if (!user2) {
            console.log("Failed! user2 doesn't exist!");
      } else if (user1 !== user2) {
        console.log("Passed! If you become older, you will be different from you in the past!")
    } else {
        console.log("Failed! User same with past one");
    }
}

agedUserMustBeDifferentFromUser(user, agedUser);
  • 두 개의 인자를 받는 getAged 함수 내의 user 를 복사해서 나이를 더하는 코드를 쓰면 된다.
  • 밑에 if문은 원래 있었던 user의 값과 새로 생성되는 getAged의 생성자를 비교해서 "passed!"를 띄우면 된다.
  • 새로운 유저 newUser를 user{} 내의 객체들을 새롭게 복사한다.
  • 복사한 값은 console.log()로 찍어 봤을 때 같은 값이 들어가 있으니 "Failed!" 가 뜨는 걸 확인 할 수 있다.

  • 참조형을 쓰고 있어서 위에서 가져온 값이 같을 수 밖에 없다는 걸 알 수 있다.
  • 그래서 순회하는 객체를 새로 만들어 주어야 한다.
var getAged = function (user, passedTime) {
        // 여기를 작성해 주세요!
        var newUser ={};
        for(var prop in user) {
            newUser[prop] = user[prop];
        }
        newUser.age += passedTime;
        return newUser;

};

 

  • newUser - {} 이렇게 빈 객체를 만들어준다.
  • for~in 문을 통해서 user 안에 있는 prop을 계속 할당해주는 방식을 채용한다.
  • 새로운 newUser에 [prop]라는 키를 가진 놈을 새롭게 user[prop]을 할당해준다.
  • 위 과정에서 console.log()로 호출 테스트를 해준다.
  • 위 상태에서 newUser의 age를 늘릴 수 있으려면 위처럼 더하기를 해주고
  • return newUser로 반환해주면 완성된다.

오늘 느낀점

배우면 배울수록 알면 알수록 더 어려워진다.

끝까지 할 수 있을까란 생각도 계속 들고

내 머리는 아메바 같다고 느껴진다 이해를 하려고 다가가도

멀어져만 가는 것 같다. 무식하게 머리를 박는게 맞나싶다.

그럼에도 일단 머리를 박아가는 이유는

나중에 회사에 들어가서 유지보수를 하게 되거나 

기존에 있는 워크스페이스 틀을 이해하는데

즉, 코드 분석과 해석을 하려면 필요한 지식이니까 일단 박는다,,

 

더 좋은 공부법은 없는지, 내가 이해하기 쉬운 구문은 없는지

찾아보고 있지만 그런 방법은 없는 것 같다. 일단 5주차까지

완주하고 복습을 하는 시간을 또 갖고 개인 프로젝트를 하다보면

실력이 늘지 않을까,, 포기하지만 않으면 반은 성공한 것일테니

지쳐도 하기 싫어도 끝까지 간다는 마인드만 바뀌지말자.

 

ps. 이 사진을 보면 모든 개발자들도 나와 같이 코딩을 어렵게 느끼는 것 같다 ㅋㅋ

'[TIL]' 카테고리의 다른 글

[TIL] 2024.01.04  (1) 2024.01.04
[TIL] 2024.01.03  (1) 2024.01.03
[TIL] 23.12.29 JS 문법 종합반 1주차  (2) 2023.12.29
[TIL] 2023.12.28  (0) 2023.12.28
[TIL] 2023.12.27  (0) 2023.12.27

관련글 더보기