본문 바로가기
TIL/HTML, CSS, JS 이것저것

Javascript Koans - About Mutability

by Dev_Dank 2021. 5. 19.

바닐라코딩 프렙 사전과제인 자바스크립트 코안스를 풀던중 mutability 파트에서 몰랐던 것이 나와서 기록해두려 한다. 

우선 mutablilty파트를 풀기 위해서는 기본적인 자바스크립트 OOP 개념(컨스트럭터 함수, 프로토타입, 상속 등)을 알아야 해서 MDN에서 해당 문서를 한번 더 복습했다.

https://developer.mozilla.org/en-US/docs/Learn/JavaScript/Objects/Object-oriented_JS

 

Object-oriented JavaScript for beginners - Learn web development | MDN

This article has provided a simplified view of object-oriented theory — this isn't the whole story, but it gives you an idea of what we are dealing with here. In addition, we have started to look at different ways of generating object instances.

developer.mozilla.org

그리고 아래부분이 내가 이해가 잘 안되었던 부분이다.

 it("should know that variables inside a constructor and constructor args are private", function () {
    function Person(firstname, lastname)
    {
      var fullName = firstname + " " + lastname;

      this.getFirstName = function () { return firstname; };
      this.getLastName = function () { return lastname; };
      this.getFullName = function () { return fullName; };
    }
    var aPerson = new Person ("John", "Smith");
    
    //여기서 aPerson 인스턴스(객체)의 속성을 Penny Andrews 라고 바꿨는데...
    aPerson.firstname = "Penny";
    aPerson.lastname = "Andrews";
    aPerson.fullName = "Penny Andrews";
    
    // 정작 컨스트럭터 함수로 상속받은 메소드에서는 위에서 속성으로 지정한 penny Andrews가 나오는게 아니라 인스턴스 생성시 입력한 John Smith가 나온다.
    expect(aPerson.getFirstName()).toBe('John');
    expect(aPerson.getLastName()).toBe('Smith');
    expect(aPerson.getFullName()).toBe('John Smith');
    

    aPerson.getFullName = function () {
      return aPerson.lastname + ", " + aPerson.firstname; // 그런데 해당 인스턴스의 메소드를 재정의 해주면
    };

    expect(aPerson.getFullName()).toBe('Andrews, Penny'); // 13~15라인에서 지정한 Penny Andrews가 나온다.
  });

주석에 언급했듯이 나는 객체의 속성을 Penny Andrews로 지정했으니 getFullName 메소드를 실행할때 전부 Penny Andrews 로 나올줄알았다. 그런데 웬걸 메소드를 재정의 하기 전까지는 인스턴스를 생성할때 입력한 John Smith가 계속 나온다. 

왜?

Koans 첫문단에서는 컨스트럭터 함수내의 변수와 인스턴스 생성시 입력된 인자는 접근이 불가능하다고 한다. 

Koans의 해당 문장을 봐도 잘 이해가 되지 않는다 ㅜㅜ... 그래서 일단 크롬 콘솔창에서 getFullName메소드를 재정의 하기전 aPerson과 재정의 한 후의 aPerson을 비교해 보았다. 

메소드 재정의전 클로저가 존재한다.
매소드 재정의 후에는 클로저가 사라진다.

비교결과 클로저? 라는 것이 메소드 재정의 전에는 존재하는데 메소드 재정의 후에는 사라지는 것을 볼수있다.

이 클로저라는 것이 원인이 되는거 같다!

클로저가 뭔지 잘 몰라 MDN에서 클로저에 관한 문서를 읽어봤는데.

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Closures

 

Closures - JavaScript | MDN

A closure is the combination of a function bundled together (enclosed) with references to its surrounding state (the lexical environment).

developer.mozilla.org

한줄로 간단하게 요약하자면 함수가 생성될때(특히 중첩함수) 함수여러개가 생성된 환경의 reference지점과 함께 번들처럼 묶여있는 상태를 의미하는거 같다. 여기서 생성된 환경이란 함수내부에서 선언된 로컬함수나 지역변수등을 포함하는 것.

지금까지 이해한 내용을 정리해보면 

Koans 예시에서는 맨처음  John Smith 라는 매개변수를 제공해서 aPerson 인스턴스 생성
=> John Smith 라는 매개변수가 aPerson의 getFullName메소드의 클로져에 포함 되어있는 상태
=> aPerson의 firstname이나 lastname 속성을 바꿔도 결국 getFullName메소드가 reference하는 지점은 클로저에 포함된 John Smith 이기 때문에 계속 John Smith가 나옴.

이게 아닌가 싶다. 

그리고 클로저는 MDN 문서에 보면 함수를 생성할때마다 생긴다고 했는데 aPerson의 getFullName메소드의 클로저가 삭제되는것도 getFullName메소드를 재정의 (=함수를 생성) 해줬기 때문인거 같다. 


2021-05-25 Poiema web 에서 관련 내용을 발견하여 추가합니다.

https://poiemaweb.com/js-object

 

Object | PoiemaWeb

자바스크립트는 객체(object)기반의 스크립트 언어이며 자바스크립트를 이루고 있는 거의 “모든 것”은 객체이다. 원시 타입(Primitives)을 제외한 나머지 값들(함수, 배열, 정규표현식 등)은 모두

poiemaweb.com

기본적으로 생성자 함수내에서 This 로 바인딩 되지 않은 변수는 생성자 함수 내부에서만 접근이 가능하다.

2021-06-20 추가내용

코어 자바스크립트의 클로저 챕터를 읽고 해당 포스팅에서 클로저때문에 막혔던 기억이 나서 돌아와서 한번 더 정리합니다. 

정말 간단히 말하자면 클로저란 함수를 반환하는 중첩함수에서 외부함수의 실행 컨텍스트가 스택에서 사라져도 내부함수는 여전히 외부함수에 정의 된 변수를 기억하고 활용할 수 있는 것을 의미합니다. (ex 디바운스 함수)

위의 예시에서 Person 생성자 함수의 fullName 변수에 this를 안붙였기 때문에 Person 생성자 함수로 만든 인스턴스에는 fullName 프로퍼티가 추가되지 않고 대신 this로 바인딩된 메소드에서 해당 인스턴스에서 사용 가능한 클로저로 연결되어 있는 것이겠네요. 

실제로 aPerson 인스턴스에는 firstName, lastName, fullName을 볼수 없죠?

그렇기 때문에 "John", "Smith" 를 매개변수로 하여 인스턴스 생성 하면 인스턴스의 메서드들만 클로저로 "John", "Smith" 를 기억하고 있는 것입니다. 

'TIL > HTML, CSS, JS 이것저것' 카테고리의 다른 글

JS30 - Playing with CSS Variables and JS  (0) 2021.05.30
JS 30 - Drum Kit  (0) 2021.05.26
숫자야구 만들기  (0) 2021.05.06
캘린더 만들어보기  (0) 2021.04.22
Carousel 웹사이트 만들어보기  (0) 2021.04.02

댓글