daily

23.04.10. 실행 컨텍스트 더 알아보기 문제

Juhyuck 2023. 4. 12. 23:26
728x90

Issue

온라인 강의 실행 컨텍스트에 대해서 알아보는 문제가 주어졌다.

 

// 가장 아래의 코드가 실행 되었을 때, “Passed ~” 가 출력되도록 getAge 함수를 채워주세요
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);
// 출력의 결과를 제출해주세요, 그리고 그 이유를 최대한 상세히 설명해주세요

var fullname = 'Ciryl Gane'

var fighter = {
    fullname: 'John Jones',
    opponent: {
        fullname: 'Francis Ngannou',
        getFullname: function () {
            return this.fullname;
        }
    },

    getName: function() {
        return this.fullname;
    },

    getFirstName: () => {
        return this.fullname.split(' ')[0];
    },

    getLastName: (function() {
        return this.fullname.split(' ')[1];
    })()

}

console.log('Not', fighter.opponent.getFullname(), 'VS', fighter.getName());
console.log('It is', fighter.getName(), 'VS', fighter.getFirstName(), fighter.getLastName);

Try&Error

 

첫번째 문제는 Object의 얕은 복사와 깊은 복사, 또는 새로운 객체 생성하는 방법에 대한 문제이다. 단순하게 새로운 함수를 정의한 다음 기존 user를 대입해버리면 객체의 주소값이 복사되므로, 두 유저의 값이 같게 되고, 어느 한쪽의 값만 수정할 수 없게 되기 때문에 원하는 결과를 얻을 수 없게 된다. 그러므로 새로운 객체를 선언하고, 새 객체의 요소와 값을 입력하는 방법으로 해결해야 한다.

 

두번째 문제는 this 바인딩 문제이다. 객체 내에서 사용되는 this가 어디에 연결되는지에 대한 것으로, 함수 표현식 중 function키워드를 사용하는 경우와 화살표 함수의 차이, 익명함수(즉시실행함수)에 대한 this 바인딩 차이를 알 수 있는 문제이다.


Solution

첫번째 문제에서 나는 newUser를 new Object로 새로운 객체를 만들고, key와 value를 entries로 불러와 넣어주었다.

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

var getAged = function (user, passedTime) {
    let newUser = new Object
    for (let [key, value] of Object.entries(user)) {
        newUser[key] = value
    }
    newUser.age += passedTime
    return newUser
}

var agedUser = getAged(user, 6);

console.log(agedUser)

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");
    }
}

console.log(agedUserMustBeDifferentFromUser(user, agedUser))

답안은 조금 달랐는데, var 키워드와 {}로 객체를 만들고, property만 for in 으로 불러와 값은 user에 key를 이용해 입력했다.

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

// 객체 만들어 프로퍼티 복사하기
var getAged = function (user, passedTime) {
    var result = {};
    for (var prop in user) {
        result[prop] = user[prop];
    }
    result.age += passedTime; 
    return result;
}


var agedUser = getAged(user, 6);

var agedUserMustBeDifferentFromUser = function (user1, user2) {
    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);

 

두번째 문제의 결과는 

// Not Francis Ngannou VS John Jones
// It is John Jones VS Ciryl Gane

인데, 당연한 결과이고 그 이유에 대해 서술하는 것이 문제이므로 적어보면,

 

this 가 어디에 바인딩 되느냐에 따라 결과가 달라지는 결과로, 가장 먼저 fighter.opponent.getFullname() 의 경우, this는 상위 object인 oppenent에 바인딩 되어있어서, this.fullname은 Francis Ngannou가 반환된다. 그 다음 fighter.getName()의 this는 함수 선언으로 생성된 요소이므로 this는 상위 객체인 fighter에 바인딩 되어, fullname은 John Jones가 됩니다.
마지막 fighter.getFirstName()과 fighter.getLastName()은 화살표 함수, 그리고 즉시실행 익명함수로 선언되어 있기 때문에 this 는 fighter 객체의 상위 객체 즉, 전역객체인 window에 바인딩 되고, 전역 변수로 선언한 fullname인 Ciryl Gane가 반환됩니다.


Learned

this 바인딩은 혼동되기 쉬운 개념이다. bind를 시켜주거나, 그 개념에 대해 잘 정리한 여러 설명글을 읽으며 자연스럽게 읽히도록 반복해서 살펴봐야한다.

 

참조하면 좋은 영상

1. 별코딩 This 와 Bind

2. 우테코 브콜의 This