"this" and Arrow Functions

With regular functions, the value of thisis set based on how the function is called. With arrow functions, the value of thisis based on the function's surrounding context. In other words, the value of this inside an arrow function is the same as the value of thisoutside the function.

Let's check out an example with thisin regular functions and then look at how arrow functions will work.

// constructor
function IceCream() {
  this.scoops = 0;
}

// adds scoop to ice cream
IceCream.prototype.addScoop = function() {
  setTimeout(function() {
    this.scoops++;
    console.log('scoop added!');
  }, 500);
};

const dessert = new IceCream();
dessert.addScoop();

Prints:
scoop added!

After running the code above, you'd_think_thatdessert.scoopswould be1after half a millisecond. But, unfortunately, it's not:

console.log(dessert.scoops);

Prints:
0

Can you tell why?

The function passed tosetTimeout()is called withoutnew, withoutcall(), withoutapply(), and without a context object. That means the value ofthisinside the function is the global object and NOTthedessertobject. So what actually happened was that a newscoopsvariable was created (with a default value ofundefined) and was then incremented (undefined + 1results inNaN):

setTimeout()에 전달된 함수는 call()이 없으면 apply()가없고 context 객체가 없으면 new없이 호출됩니다. 즉, 이 함수 내부 값은 디저트 객체가 아니라 전역 객체입니다. 그래서 실제적으로 새로운 scoops 변수가 만들어졌고 (기본값은 undefined 임) 다음 증분되었습니다 (NaN에서 undefined + 1 결과).

console.log(scoops);

Prints:
NaN

One way around this is to use closure:

// constructor
function IceCream() {
  this.scoops = 0;
}

// adds scoop to ice cream
IceCream.prototype.addScoop = function() {
  const cone = this; // sets `this` to the `cone` variable
  setTimeout(function() {
    cone.scoops++; // references the `cone` variable
    console.log('scoop added!');
  }, 0.5);
};

const dessert = new IceCream();
dessert.addScoop();

The code above_will_work because instead of usingthisinside the function, it sets theconevariable tothisand then looks up theconevariable when the function is called. This works because it's using the value of thethisoutside the function. So if we check the number of scoops in our dessert right now, we'll see the correct value of1:

위의 코드는 함수 내부에서 this를 사용하는 대신 cone 변수를 this로 설정하고 함수가 호출 될 때 cone 변수를 조회하기 때문에 작동합니다. 이것은 함수 외부의 this의 값을 사용하기 때문에 작동합니다. 따라서 디저트의 스푼 수를 지금 확인하면 올바른 값인 1이 표시됩니다.

console.log(dessert.scoops);

Prints:
1

Well that's exactly what arrow functions do, so let's replace the function passed tosetTimeout()with an arrow function:

// constructor
function IceCream() {
  this.scoops = 0;
}

// adds scoop to ice cream
IceCream.prototype.addScoop = function() {
  setTimeout(() => { // an arrow function is passed to setTimeout
    this.scoops++;
    console.log('scoop added!');
  }, 0.5);
};

const dessert = new IceCream();
dessert.addScoop();

Since arrow functions inherit theirthisvalue from the surrounding context, this code works!

console.log(dessert.scoops);

Prints:
1

WhenaddScoop()is called, the value ofthisinsideaddScoop()refers todessert. Since an arrow function is passed tosetTimeout(), it's using its surrounding context to determine whatthisrefers to inside itself. So sincethis_outside_of the arrow function refers todessert, the value ofthis_inside_the arrow function will also refer todessert.

addScoop()이 호출되면 addScoop() 내부의 값은 디저트를 참조합니다. Arrow function은 setTimeout()에 전달되기 때문에 주위의 컨텍스트를 사용하여 이 함수가 내부적으로 무엇을 참조하는지 결정합니다. 따라서 arrow function 바깥 쪽은 디저트를 참조하기 때문에 화살표 함수 내부의 값도 디저트를 나타냅니다.

Now what do you think would happen if we changed theaddScoop()method to an arrow function?

// constructor
function IceCream() {
    this.scoops = 0;
}

// adds scoop to ice cream
IceCream.prototype.addScoop = () => { // addScoop is now an arrow function
  setTimeout(() => {
    this.scoops++;
    console.log('scoop added!');
  }, 0.5);
};

const dessert = new IceCream();
dessert.addScoop();

Yeah, this doesn't work for the same reason - arrow functions inherit theirthisvalue from their surrounding context. Outside of theaddScoop()method, the value ofthisis the global object. So ifaddScoop()is an arrow function, the value ofthisinsideaddScoop()is the global object. Which then makes the value ofthisin the function passed tosetTimeout()_also_set to the global object!

results matching ""

    No results matching ""