February 12, 2020
리액트 문법을 중 class를 이해하기 위한 포스팅
앞선 포스트에서 this가 생성자 함수에서 생긴 인스턴스 객체의 호출자 역할을 한다고 알아보았다.
그럼 생성자 함수에서 생긴 인스턴스 객체를 호출하면 항상 그 객체의 속성만 써야할까?
하나의 인스턴스 객체를 통해 호출한 함수를 쓰면서, 다른 인스턴스 객체의 속성들을 사용하기 위해 나온게 위 메소드들이다.
객체를
바인딩
한다고 한다.
var example = function(a, b, c) {
return a + b + c
}
example(1, 2, 3)
example.call(null, 1, 2, 3)
example.apply(null, [1, 2, 3])
함수를 호출하게 되면 호출자는 브라우저에서는 this, 모듈내에서는 해당 모듈을 의미한다. nodeJS 에서는 global.
즉, 기본적으로 this는 전역객체에 바인딩
된다. (새로 인스턴스를 만들고 그 인스턴스로 호출하지 않는이상)
근데 함수 내장 메소드 call apply 방식으로 this를 지정해줄 수 있다.
하지만 ‘use strict’ 를 통해 전역객체의 바인딩을 방지할 수도 있다.
call
: parameter로 바인딩할 객체, arguments가 하나하나 들어감
apply
: parameter로 바인딩할 객체, arguments가 배열형태로 들어감
// 객체 내부 함수에 직접 call을 적용
var obj = {
string: 'zero',
yell: function() {
alert(this.string)
},
}
var obj2 = {
string: 'what?',
}
obj.yell() // 'zero';
obj.yell.call(obj2) // 'what?'
var obj = {
string: 'zero',
yell: function() {
alert(this.string)
},
}
var obj2 = {
string: 'what?',
}
var yell2 = obj.yell.bind(obj2)
yell2() // 'what?'
class App extends React.Component {
constructor() {
super()
this.handler = this.handler.bind(⭐this)
}
handler() {
⭐this.setState({
// ...
})
}
render() {
return <div onClick={this.handler} />
}
}
이 화살표 함수부터가 본격적인 ES6 문법
이다.
JAVA의 람다식과 유사한 형태..!
function(x) {return x}
x => {
return x
}
parameter => { 함수 식 } 형태로 줄여서 쓴다.
var obj = {
name: '태니',
func: function() {
// 또다른 콜백 function ...이 있으면
function(){}.bind(this)
// 대신에
() => {}
}
};
obj.func();
객체의 메소드를 호출했는데 그안에 또다른 콜백 함수가 들어있는데 그 함수가 객체 내부의 상태(속성)을 참고하기 위해선 bind(this)를 통해 객체를 바인딩 해주어야한다. (혹은 bind(otherObject))
화살표함수는 Lexical this
라고 함수가 선언되었을 때의 상위 스코프의 this를 유지한다.
bind(this)를 안해줘도 됨.
메소드
// Bad
const person = {
name: 'Lee',
sayHi: () => console.log(`Hi ${this.name}`),
}
person.sayHi() // Hi undefined
// Good
const person = {
name: 'Lee',
sayHi() {
// === sayHi: function() {
console.log(`Hi ${this.name}`)
},
}
person.sayHi() // Hi Lee
이벤트 리스너
// Bad
var button = document.getElementById('myButton')
button.addEventListener('click', () => {
console.log(this === window) // => true
this.innerHTML = 'Clicked button'
})
// Good
var button = document.getElementById('myButton')
button.addEventListener('click', function() {
console.log(this === button) // => true
this.innerHTML = 'Clicked button'
})
class Comp extends React.Component {
handler = () => {
console.log(this)
}
render() {
return (
<button type="button" onClick={this.handler}>
Goodbye bind
</button>
)
}
}
export default Comp
const Comp = ({ props }) => {
return <div></div>
}
export default Comp
var foo = ['one', 'two', 'three']
var [one, two, three] = foo
console.log(one) // "one"
console.log(two) // "two"
console.log(three) // "three"
var a = 1
var b = 3
;[a, b] = [b, a]
console.log(a) // 3
console.log(b) // 1
const obj = {
name: `태니`,
}
const { name } = obj
console.log(name)
var o = { p: 42, q: true }
var { p, q } = o
console.log(p) // 42
console.log(q) // true
const { state1 } = this.state
const { state2 } = this.props
const Comp = ({ props }) => {
return <div></div>
}
export default Comp
여기서 { props } 를 쓰는 이유 : parameter로 props객체가 들어온다. 구조분해로 이 객체를 props로 사용가능.
ECMAScript 2015(ES6) 부터 javascript 에 class 문법이 도입되었다.
class Rectangle {
constructor(height, width) {
this.height = height
this.width = width
}
}
var rect = new Rectangle(4, 5)
console.log(rect.height)
기존에 constructor속성은 인스턴스 객체의 prototype 원형객체를 만든 생성자함수를 참조하였다.
class에서는 constructor 메소드를 통해 만들어질 객체에 대한 정보를 초기화한다.
function taeny() {
this.name = '태니'
}
class taeny {
constructor() {
this.name = '태니'
}
speak() {
return this
}
static eat() {
return this
}
}
super 메소드는 부모 클래스의 constructor 정보를 상속받을 수 있다.
Math.method 처럼 class의 인스턴스 객체가 아니라 class를 호출해서 사용할 수 있는 메소드
상속된 클래스는 메소드 오버라이딩이 가능해진다.