11) 자바스크립트 X ES -2 (this, arrow function, 구조분해, class)

0. Intro

리액트 문법을 중 class를 이해하기 위한 포스팅

자바스크립트 X 리액트

1. this

1-1. call bind apply

앞선 포스트에서 this가 생성자 함수에서 생긴 인스턴스 객체의 호출자 역할을 한다고 알아보았다.

그럼 생성자 함수에서 생긴 인스턴스 객체를 호출하면 항상 그 객체의 속성만 써야할까?

하나의 인스턴스 객체를 통해 호출한 함수를 쓰면서, 다른 인스턴스 객체의 속성들을 사용하기 위해 나온게 위 메소드들이다.

객체를 바인딩 한다고 한다.

1. 함수호출방식

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’ 를 통해 전역객체의 바인딩을 방지할 수도 있다.

use strict 에서 this

call : parameter로 바인딩할 객체, arguments가 하나하나 들어감

apply : parameter로 바인딩할 객체, arguments가 배열형태로 들어감

2. call, apply(호출시 외부 객체 바인딩)

// 객체 내부 함수에 직접 call을 적용
var obj = {
  string: 'zero',
  yell: function() {
    alert(this.string)
  },
}
var obj2 = {
  string: 'what?',
}
obj.yell() // 'zero';
obj.yell.call(obj2) // 'what?'

출처

3. bind (외부 객체 바인딩)

var obj = {
  string: 'zero',
  yell: function() {
    alert(this.string)
  },
}
var obj2 = {
  string: 'what?',
}
var yell2 = obj.yell.bind(obj2)
yell2() // 'what?'

출처

4. 리액트에서의 bind

class App extends React.Component {
  constructor() {
    super()
    this.handler = this.handler.bind(this)
  }

  handler() {this.setState({
      // ...
    })
  }

  render() {
    return <div onClick={this.handler} />
  }
}

2. arrow function

이 화살표 함수부터가 본격적인 ES6 문법이다.

JAVA의 람다식과 유사한 형태..!

2-1. 간결해진 코드

function(x) {return x}

x => {
  return x
}

parameter => { 함수 식 } 형태로 줄여서 쓴다.

2-2. 자동 바인딩 (Lexical this)

var obj = {
  name: '태니',
  func: function() {
    // 또다른 콜백 function ...이 있으면
    function(){}.bind(this)
    // 대신에
    () => {}
  }
};
obj.func();

객체의 메소드를 호출했는데 그안에 또다른 콜백 함수가 들어있는데 그 함수가 객체 내부의 상태(속성)을 참고하기 위해선 bind(this)를 통해 객체를 바인딩 해주어야한다. (혹은 bind(otherObject))

화살표함수는 Lexical this라고 함수가 선언되었을 때의 상위 스코프의 this를 유지한다.

bind(this)를 안해줘도 됨.

실행컨텍스트>lexical scoping

2-3. 화살표함수 쓸 때 주의할 점.

참고사이트

메소드

// 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'
})

2-4. 리액트에서의 화살표함수

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

3. 구조 분해 할당

3-1. 배열 구조 분해

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

3-2. 객체 구조 분해

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

3-3. 리액트에서의 사용법1

const { state1 } = this.state
const { state2 } = this.props

3-4. 리액트에서의 사용법2

const Comp = ({ props }) => {
  return <div></div>
}

export default Comp

여기서 { props } 를 쓰는 이유 : parameter로 props객체가 들어온다. 구조분해로 이 객체를 props로 사용가능.

4. class

ECMAScript 2015(ES6) 부터 javascript 에 class 문법이 도입되었다.

  1. 클래스도 함수다.
  2. 클래스의 내부는 ‘use strict’ 모드이다.
  3. 여전히 js 프로토타입 모델을 사용한다.
  4. 함수 선언의 경우 호이스팅이 일어나지만, 클래스 선언은 그렇지 않는다. ❓ why?
class Rectangle {
  constructor(height, width) {
    this.height = height
    this.width = width
  }
}

var rect = new Rectangle(4, 5)
console.log(rect.height)

4-1. constructor

기존에 constructor속성은 인스턴스 객체의 prototype 원형객체를 만든 생성자함수를 참조하였다.

Object.prototype.constructor

class에서는 constructor 메소드를 통해 만들어질 객체에 대한 정보를 초기화한다.

function taeny() {
  this.name = '태니'
}

class taeny {
  constructor() {
    this.name = '태니'
  }
  speak() {
    return this
  }
  static eat() {
    return this
  }
}

4-2. super

super 메소드는 부모 클래스의 constructor 정보를 상속받을 수 있다.

4-3. static method (정적 메소드)

Math.method 처럼 class의 인스턴스 객체가 아니라 class를 호출해서 사용할 수 있는 메소드

4-4. 메소드 오버라이딩

상속된 클래스는 메소드 오버라이딩이 가능해진다.

❓ 클래스 호이스팅, TDZ 학습

Written by@taenyKim
웹 프론트엔드 공부 블로그 / Learn in Public

GitHubFacebook