자바스크립트 this
업데이트:
1. 자바스크립트에서의 this
자바스크립트를 공부하면서 this
에 대해 알 듯 모를 듯 해서 이번기회에 예제를 이용해 다시 정리해봅니다.
언어마다 어느정도 차이가 있겠지만 대표적으로 자주 사용하는 JAVA에서의 this
키워드는 자기자신을 가리키는 키워드입니다. 즉 this
키워드를 통해 클래스 메서드 및 생성자에서 자신의 데이터를
업데이트하거나 조작할 수 있습니다.
하지만 자바스크립트의 this
는 조금 다릅니다. 간단히 설명하자면 자바스크립트에서의 this
는 호출한 곳을 가리키게 됩니다.
React로 만든 구구단 예제를 통해 this에 대해 알아보겠습니다.
2. React 구구단 예제를 통해 알아보는 this
create-react-app을 사용하지 않고 html파일에 그대로 복사붙여넣기하면 됩니다.
2.1 구구단예제 html 소스
<!doctype html>
<html lang="ko">
<head>
<meta charset="UTF-8">
<meta name="viewport"
content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<script src="https://unpkg.com/react@16/umd/react.development.js"></script>
<script src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script>
<script src="https://unpkg.com/babel-standalone@6/babel.min.js"></script>
<title>React Study</title>
</head>
<body>
<div id="root"></div>
<script type="text/babel">
class GuGuDan extends React.Component {
constructor( props ) {
super(props);
this.state = {
num1 : this.random(2, 9),
num2 : this.random(1, 9),
value : '',
result: ''
};
// this.onSubmit = this.onSubmit.bind(this);
console.log(this);
}
random( min, max ) {
return Math.floor(( Math.random() * ( max - min + 1 ) ) + min);
};
resetRandom() {
this.setState({
num1: this.random(2, 9),
num2: this.random(1, 9),
});
};
resetValue() {
this.setState({
value: ''
});
}
onSubmit( e ) {
e.preventDefault();
if (( this.state.num1 * this.state.num2 ) === parseInt(this.state.value)) {
this.setState(( prevState ) => {
return {
result: `${prevState.num1} x ${prevState.num2} = ${prevState.value} | 정답 ✅`
};
});
this.resetRandom();
this.resetValue();
} else {
this.setState(( prevState ) => {
return {
result: `${prevState.num1} x ${prevState.num2} = ${prevState.value} | 땡 ❌`
};
});
this.resetValue();
}
};
onChange = ( e ) => {
this.setState({
value: e.target.value,
});
};
render() {
return (
<React.Fragment>
<h1>{this.state.num1} X {this.state.num2} ??</h1>
<form onSubmit={this.onSubmit}>
<input type="number" value={this.state.value} onChange={this.onChange}/>
<button>입력</button>
</form>
<div>{this.state.result}</div>
</React.Fragment>
);
}
}
</script>
<script type="text/babel">
ReactDOM.render(
<React.Fragment>
<GuGuDan/>
</React.Fragment>, document.querySelector('#root')
);
</script>
</body>
</html>
우선 위의 코드를 복사해서 .html 파일안에 붙여넣어서 실행하세요!
2.2 구구단예제 실행 결과
실행하면 위와 같은 화면이 뜨고 숫자를 입력할 수 있는 input창 하나가 존재합니다. 이제 숫자를 입력하고 입력버튼을 눌러보겠습니다.
아무런 반응이 없죠?? 저희는 분명
<form onSubmit={this.onSubmit}>
<input type="number" value={this.state.value} onChange={this.onChange}/>
<button>입력</button>
</form>
onSubmit(e)
{
console.log(this); // undefined
e.preventDefault();
if (( this.state.num1 * this.state.num2 ) === parseInt(this.state.value)) {
this.setState(( prevState ) => {
return {
result: `${prevState.num1} x ${prevState.num2} = ${prevState.value} | 정답 ✅`
};
});
this.resetRandom();
this.resetValue();
} else {
this.setState(( prevState ) => {
return {
result: `${prevState.num1} x ${prevState.num2} = ${prevState.value} | 땡 ❌`
};
});
this.resetValue();
}
}
;
입력버튼을 누르면 this.onSubmit
함수가 동작해야 하는데 동작이 되질 않습니다.
이러한 오류가 생기는 이유는 this
키워드는 호출한 곳을 가리키게 되서 그렇습니다.
onSubmit(e) {} 함수에 console.log(this)
를 찍어보면 undefined
가 찍히는 것을 볼 수 있습니다.
우리가 this
키워드를 사용해서 GuGuDan class의 onSubmit 함수를 가리키게 하려면 bind
를 해줘야합니다.
bind
를 해주는 방법은 클래스 생성자 constructor() { … } 안에 this.onSubmit = this.onSubmit.bind(this);
사용해서 GuGuDan class객체가 생성될 때
onSubmit을 bind(묶다)
해주면 앞으로 어디서든 this
키워드를 사용해서 onSubmit()함수를 불러올 수 있습니다.
2.3 조금 더 쉽게 이해하는 방법
저도 처음 자바스크립트를 접하고 this에 대해 많이 헷갈렸습니다. (물론 지금도..😂)
위와 같은 설명이 잘 이해가 가지 않으신 분은 조금 더 이해하기 좋은 방법이라고 생각합니다.
제가 조금 더 이해하는데 도움되었던 확인 방법은 class를 생성했을 때 constructor() {} 생성자 함수 내에서 console.log(this)
를 찍어보는 것 이었습니다.
우선 구구단 클래스에 생성자 함수에서 this.onSubmit을 바인딩 해준 것을 다시 주석처리하고 console.log(this)
를 해보도록 하겠습니다.
class GuGuDan extends React.Component {
constructor( props ) {
super(props);
this.state = {
num1 : this.random(2, 9),
num2 : this.random(1, 9),
value : '',
result: ''
};
//this.onSubmit = this.onSubmit.bind(this);
console.log(this);
}
...
...
2.3.1 onSubmit 바인딩 안해줬을 때
바인딩 안해줬을 때 GuGuDan 클래스의 this는 onSubmit 함수를 포함하고 있지 않음
2.3.2 onSubmit 바인딩 해줬을 때
바인딩 해줬을 때 GuGuDan 클래스의 this는 onSubmit 함수를 포함하고 있음
bind
를 해줬을 때와 안해줬을 때 클래스에서의 this가 가지고 있는 객체들
bind
를 안해줬을 때 this
키워드가 onSubmit 함수를 찾지못한 이유는
<form onSubmit={this.onSubmit}>
<input type="number" value={this.state.value} onChange={this.onChange}/>
<button>입력</button>
</form>
와 같이 form에서 this
키워드가 불러졌고 this
키워드는 앞서 설명한 것과 같이 호출한 곳을 가리킵니다.
2.4 화살표 함수를 사용하는 이유!!
화살표 함수는 ES6 문법으로 const name = () => {}
와 같이 사용합니다.
예제와 같이 onSubmit(e){} 와 같이 함수를 선언하게 되면 bind
작업이 필요하지만 화살표 함수를 사용하게 되면 클래스 내에 자동으로 bind 해줍니다. 귀찮게 일일이 bind
해줄 필요가 없습니다.
onSubmit (e) { } // bind 필요
onSubmit = ( e ) => { } // 자동으로 class에 bind 해줌
직접 확인해보시려면 위의 html코드 예제에서 생성자 함수인 constructor안에 있는 this.onSubmit = this.onSub...
를 삭제하시면 됩니다!
2.5 random, resetRandom, resetValue 함수 bind
가 필요 없는 이유
다시 한 번 말하자면 this
키워드는 호출된 곳을 가리킵니다. random
,resetRandom
,resetValue
함수는 같은 클래스 내에서 호출이 이루어지므로 각각의
함수에 console.log(this)
를 해보면 GuGuDan 클래스를 가리키는 것을 확인할 수 있습니다.
random(min, max)
{
console.log('random');
console.log(this);
return Math.floor(( Math.random() * ( max - min + 1 ) ) + min);
}
resetRandom()
{
console.log('resetRandom');
console.log(this);
this.setState({
num1: this.random(2, 9),
num2: this.random(1, 9),
});
}
resetValue()
{
console.log('resetValue');
console.log(this);
this.setState({
value: ''
});
}
만약 아래와 같이 숫자를 바꿀 수 있는 버튼을 만들었고
<React.Fragment>
<h1>{this.state.num1} X {this.state.num2} ??</h1>
<form onSubmit={this.onSubmit}>
<input type="number" value={this.state.value} onChange={this.onChange}/>
<button>입력</button>
</form>
<button type="submit" onClick={this.resetRandom}>숫자 바꾸기</button>
<div>{this.state.result}</div>
</React.Fragment>
숫자 바꾸기 button
을 클릭했을 때 resetRandom
함수를 호출하려면 resetRandom
을 직접 bind
해주거나, resetRandom = () => {}
화살표 함수로
바꿔주기만 하면 됩니다.
참고
MDN
댓글남기기