관리 메뉴

Dev Blog

1-1. IM Prep - modern JavaScript 본문

BootCamp_Codestates/IM Tech Blog

1-1. IM Prep - modern JavaScript

Nomad Kim 2020. 12. 3. 01:15
  • 화살표 함수
  • this 키워드
  • call, apply 메소드
  • bind 메소드

화살표 함수

 

1. 함수 표현식을 축약할 수 있다.

  1) function 제거하고  인수 다음에 =>  추가

  2) return 제거(본문에 return만 있는경우) or {} + return 조합

 

2. call, apply, bind 사용불가

var adder = {
  base : 1,

  addThruApply : function(a) {
    var f = v => v + this.base;
    var b = {
      base : 100
    };
    return f.apply(b, [a]);
  },

  addThruCall: function(a) {
    var f = v => v + this.base;
    var c = {
      base : 100
    };
    return f.call(c, a);
  }
};

adder.addThruApply(1); // 2
adder.addThruCall(1);  // 2

 

3. 바인딩 되지 않는 this

function Person() {
  // Person() 생성자는 `this`를 자신의 인스턴스로 정의.
  this.age = 0;

  setInterval(function growUp() {
    // 비엄격 모드에서, growUp() 함수는 `this`를
    // 전역 객체로 정의하고, 이는 Person() 생성자에
    // 정의된 `this`와 다름.
    this.age++;
  }, 1000);
}

var p = new Person();

위 함수에서 this는 전역 객체로 정의되기 때문에, this.age 는 0부터 시작하지 않습니다.

따라서 아래와 같이 비전역 변수에 this를 할당하여 해결할 수 있습니다.

function Person() {
  var that = this;
  that.age = 0;

  setInterval(function growUp() {
    // 콜백은  `that` 변수를 참조하고 이것은 값이 기대한 객체이다.
    that.age++;
  }, 1000);
}

이와 달리 화살표 함수는 자신의 this가 없습니다.  대신 화살표 함수를 둘러싸는 렉시컬 범위(lexical scope)의 this가 사용됩니다. 즉, 현재 범위에서 존재하지 않는 this를 찾을 때, 화살표 함수는 바로 바깥 범위에서 this를 찾는것으로 검색을 끝내게 됩니다.

function Person(){
  this.age = 0;

  setInterval(() => {
    this.age++; // |this|는 Person 객체를 참조
  }, 1000);
}

var p = new Person();

의도된대로 setInterval 내의 this는 p 를 가리키기 때문에 this.age 는 0부터 순차적으로 증가합니다.

 


this키워드

 

this는 함수 실행시 호출(invocation) 방법에 의해 결정되는 특별한 객체

 

패턴 바인딩되는 객체 설명
Method 호출; obj.foo() 부모 객체 (실행 시점에 온점 왼쪽에 있는 객체) 하나의 객체에 값과 연관된 메소드를 묶어서 사용할 때 주로 사용함
new 키워드를 이용 생성자 호출; new foo() 새롭게 생성된 인스턴스 객체 객체 지향 프로그래밍에서 주로 사용함
.call 또는 .apply 호출;
foo.call() foo.apply()
첫번째 인자로 전달된 객체 this 값을 특정할 때 사용하며, 특히 apply의 경우 배열의 엘리먼트를 풀어서 인자로 넘기고자 할 때 유용함
Global; console.log(this) window (strict mode에서는 undefined) module.exports(전역에서 this 참조)
Function; 호출 foo() window (strict mode에서는 undefined) global

 

  • 브라우저 환경에서 this는 기본적으로 window 객체
  • node.js 환경에서 this는 기본적으로 module.exports 객체
  • node.js 환경에서는 global이라는 객체가 존재

Method 호출

: 객체의 속성 값으로 담긴 함수

화살표 함수로 작성된 메소드 호출시 this = module.exports

메소드 선언시 화살표 함수 사용X or 화살표 함수 사용시 this 사용X

 

생성자 호출

: 객체를 new 키워드를 이용해 만듦.

객체 = 인스턴트.  인스턴트.메소드() 형태의 호출.

new가 안 붙은 경우, this는 전역 객체를 가리킨다.

 

함수에도 메소드가 있다 => call(), apply(), bind()


call 메소드

 

.call 호출은 명시적으로 this를 지정할 때 사용. 첫번째 인자가 항상 this.

foo.call(context). context를 this로 지정하고, foo() 함수를 실행.

 

call의 두번째 인자 이후로는 파라미터로 전달됨.

function printProfile(name, age, ...args) {
  return `${this.type} ${name} 나이:${age}${args.length === 0 ? "" : " " + this.feature + ":" + args.join(",")}`;
}

const artist = { type: "아티스트", feature: "노래" };
printProfile.call(artist, "BTS", 7, "ON", "Dynamite")
//아티스트 BTS 나이:7 노래:ON,Dynamite

apply 메소드

 

.apply 호출은 명시적으로 this를 지정할 때 사용. 첫번째 인자가 항상 this.

apply의 두번째 인자는 배열.

function printProfile(name, age, ...args) {
  return `${this.type} ${name} 나이:${age}${args.length === 0 ? "" : " " + this.feature + ":" + args.join(",")}`;
}
const artist = { type: "아티스트", feature: "노래" };
printProfile.apply(artist, ["BTS", 7, "ON", "Dynamite"])
//아티스트 BTS 나이:7 노래:ON,Dynamite

 

prototype 기능 빌려쓰기

const array1 = ["code", "states"];
const array2 = ["immersive", "course"];
const arrayNumbers = [5, 10, 4, 9];

Array.prototype.concat.call(array1, array2, arrayNumbers)
//["code","states","immersive","course", 5, 10, 4 ,9]
Array.prototype.concat.apply(array1, [array2])
//["code","states","immersive","course"]

유사 배열 다루기 가능

const nodeList = {
    length: 3,
    0: "div#target",
    1: "li",
    2: "span#new"
  };

Array.prototype.slice.apply(nodeList, [0, 1]) // ["div#target"]
Array.prototype.map.call(nodeList, node => node.split("#")[0]) //["div","li","span"]

일반 배열 예시


bind 메소드

bind는 함수를 실행하지 않고, this 컨텍스트를 담은 함수를 리턴.

bind의 인자 순서는 call과 동일.

 

CASE1

: 각 버튼을 클릭했을때 클릭된 버튼의 이름이 출력되게 하려면?

 

Solution1

user를 this로 바인딩 시키는 방법

solution2

this를 사용하지 않고, 인자를 전달하는 방법

solution3

bind를 사용하지 않고 인자를 전달하는 방법

CASE2: setTimeOut

setTimeout은 시간 지연을 일으킨 후 callback 함수를 비동기적으로 실행시키는 함수입니다.

이 함수는 명시적으로 항상 window 객체를 this 바인딩하는 특징이 있습니다.

따라서, 아래와 같이 Error가 발생한다.

solution1

bind를 사용하여 해결하는 방법

solution2

익명함수를 사용하여 this를 새 변수에 담아 전달하는 방법(권장x)

solution3

화살표함수를 사용하여 해결하는 방법.

현재 범위에서 존재하지 않는 this를 찾을 때, 화살표 함수는 바로 바깥 범위에서 this를 찾는것으로 검색을 끝내게 됩니다.

Comments