Posts 모던 자바스크립트 #4.4. 메서드와 this
Post
Cancel

모던 자바스크립트 #4.4. 메서드와 this

모던 JavaScript 튜토리얼을 따라가면서 정리합니다.

4.4. 메서드와 this

  • 객체는 사용자, 주문 등 실제 존재하는 개체(entity)를 표현하고자 할 때 생성된다.
  • 사용자는 현실에서 장바구니에서 물건 선택하기, 로그인하기 등 행동을 한다. 마찬가지로 사용자를 나타내는 객체 user도 특정한 행동을 할 수 있다.
  • 자바스크립트에서는 객체의 프로퍼티에 함수를 할당해 객체에게 행동할 수 있는 능력을 부여한다.

메서드 만들기

객체 user에게 인사할 수 있는 능력을 부여한다.

1
2
3
4
5
6
7
8
9
10
let user = {
  name: "John",
  age: 30
};

user.sayHi = function() {
  alert("안녕하세요!");
};

user.sayHi(); // 안녕하세요!
  • 객체 프로퍼티에 할당된 함수메서드(method)라고 부른다.

  • 메서드는 이미 정의된 함수를 이용해서 만들 수도 있다.

    1
    2
    3
    4
    5
    6
    7
    
    function sayHi() {
      alert("안녕하세요!");
    };
      
    user.sayHi = sayHi;
      
    user.sayHi(); // 안녕하세요!
    
  • 메서드 단축 구문을 사용하면 객체 리터럴 안에 메서드를 선언할 수 있다.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    
    user = {
      sayHi: function() {
        alert("Hello");
      }
    };
      
    // 단축 구문
    user = {
      sayHi() { // "sayHi: function()"과 동일
        alert("Hell");
      }
    }
    

메서드와 this

  • 메서드 내부에서 this 키워드를 사용하면 객체에 접근할 수 있다.

    이때 점 앞의 this는 메서드를 호출할 때 사용된 객체를 나타낸다. (user.sayHi()가 실행되는 동안에 thisuser를 나타냅니다.)

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    
    let user = {
      name: "John",
      age: 30,
        
      sayHi() {
        // 'this'는 '현재 객체'를 나타낸다.
        alert(this.name);
      }
        
    };
      
    user.sayHi(); // John
    
  • this를 사용하지 않고 외부 변수를 참조해 객체에 접근하는 것도 가능하다.

  • 그러나 외부 변수를 사용해 객체를 참조하면 예상치 못한 에러가 발생할 수 있다.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    
    let user = {
      name: "John",
      age: 30,
      
      sayHi() {
        alert( user.name ); // Error: Cannot read property 'name' of null
      }
      
    };
      
      
    let admin = user;
    user = null; // user를 null로 덮어 쓴다.
      
    admin.sayHi(); // sayHi()가 엉뚱한 객체를 참고하면서 에러가 발생했다.
    

자유로운 this

  • 자바스크립트에서는 모든 함수에 this를 사용할 수 있다.

  • this 값은 런타임에 결정된다. 컨텍스트에 따라 달라진다.

    동일한 함수라도 다른 객체에서 호출했다면 this가 참조하는 값이 달라진다.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    
    let user = { name: "John" };
    let admin = { name: "Admin" };
      
    function sayHi() {
      alert( this.name );
    }
      
    // 별개의 객체에서 동일한 함수를 사용함
    user.f = sayHi;
    admin.f = sayHi;
      
    // 'this'는 '점(.) 앞의' 객체를 참조하기 때문에
    // this 값이 달라짐
    user.f(); // John (this == user);
    admin.f(); // Admin (this == admin);
      
    admin['f'](); // Admin (점과 대괄호는 동일하게 동작함)
    
  • 객체 없이 호출하면 this == undefined

    1
    
    sayHi(); // undefined
    

    엄격 모드에서 실행하면 this에는 undefined가 할당된다.

    엄격 모드가 아닐 때는 this가 전역 객체(브라우저에서는 window)를 참조한다.

자유로운 this가 만드는 결과

  • bound this: 다른 언어에서 this는 항상 메서드가 정의된 객체를 참조한다.
  • 자바스크립트에서 this는 런타임 결정되고, 메서드가 어디서 정의되었는지 상관 없이 this는 점 앞의 객체가 무엇인가에 따라 자유롭게 결정된다.
  • 함수를 하나만 만들어 여러 객체에서 재사용할 수 있다는 것은 장점이지만, 이런 유연함이 실수로 이어질 수 있다는 단점이 있다.

‘this’가 없는 화살표 함수

  • 화살표 함수는 일반 함수와 달리 ‘고유한’ this를 가지지 않는다.

  • 화살표 함수에서 this를 참조하면 화살표 함수가 아닌 평범한 외부 함수에서 this 값을 가져온다.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    
    let user = {
      firstName: "보라",
      sayHi() {
        let arrow = () => alert(this.firstName);
        arrow();
      }
    };
      
    user.sayHi(); // 보라
    
  • 별개의 this가 만들어지는 것은 원치 않고, 외부 컨텍스트에 있는 this를 이용하고 싶은 경우 화살표함수가 유용하다.

과제

객체 리터럴에서 ‘this’ 사용하기

1
2
3
4
5
6
7
8
9
10
function makeUser() {
  return {
    name: "John",
    ref: this
  };
};

let user = makeUser(); // { name: "John", ref: undefined }

alert( user.ref.name ); // Error: Cannot read property 'name' of undefined

this 값은 호출 시점에 결정된다. makeUser()가 메서드로써 호출된 게 아니라 함수로써 호출되었기 때문에 this는 undefined가 된다.

에러가 발생하지 않게 하려면 코드를 다음과 같이 수정한다.

1
2
3
4
5
6
7
8
9
10
11
12
function makeUser() {
  return {
    name: "John",
    ref() {
      return this;
    }
  };
};

let user = makeUser();

alert( user.ref().name ); // John

계산기 만들기

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
let calculator = {
  
  read() {
  	this.firstParam = +prompt("첫 번째 피연산자", "");
    this.secondParam = +prompt("두 번째 피연산자", "");
  },
  
  sum() {
    return this.firstParam + this.secondParam;
  },
  
  mul() {
    return this.firstParam * this.secondParam;
  }
  
};

calculator.read();
alert( calculator.sum() );
alert( calculator.mul() );

체이닝

1
2
3
4
5
6
7
8
9
10
11
12
let ladder = {
  step: 0,
  up() {
    this.step++;
  },
  down() {
    this.step--;
  },
  showStep: function() { // 사다리에서 몇 번째 단에 올라와 있는지 보여줌
    alert( this.step );
  }
};

메서드를 연이어 호출하려면 다음과 같이 해야 한다.

1
2
3
4
ladder.up();
ladder.up();
ladder.down();
ladder.showStep(); // 1

up, down, showStep을 수정해 메서드 호출 체이닝이 가능하게 해보자.

1
ladder.up().up().down().showStep(); // 1

해답

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
let ladder = {
  step: 0,
  up() {
    this.step++;
    return this;
  },
  down() {
    this.step--;
    return this;
  },
  showStep: function() { // 사다리에서 몇 번째 단에 올라와 있는지 보여줌
    alert( this.step );
    return this;
  }
};
This post is licensed under CC BY 4.0 by the author.

모던 자바스크립트 #4.3. 가비지 컬렉션

모던 자바스크립트 #4.5 new 연산자와 생성자 함수

Loading comments from Disqus ...