nas5w / javascript-tips-and-tidbits

A continuously-evolving compendium of javascript tips based on common areas of confusion or misunderstanding.
MIT License
1.2k stars 71 forks source link

Functions vs. arrow functions #11

Open nas5w opened 5 years ago

Kaushal28 commented 5 years ago

So am I supposed to post the difference with the examples here? If not, what you want to discuss?

nas5w commented 5 years ago

Basically I'd just like to have a discussion on what you think the section would look like. Can you post a first draft?

I like to structure it as a simple definition of the concept and then some short examples.

Thanks!

Kaushal28 commented 5 years ago

Sure! Give me some time and will post a draft here.

Kaushal28 commented 5 years ago

Arrow functions vs. function declaration


Arrow functions and function declarations are not the same/equivalent and can not be used as alternatives of each other. Here are two major differences between arrow function and function declaration.

1) Lexical this and argument binding:


Arrow functions are basically anonymous functions. They don't have their own this or arguments binding. Instead, those identifiers are resolved in the lexical scope like any other variable. That means that inside an arrow function, this and arguments refer to the values of this and arguments in the environment the arrow function is defined in (i.e. "outside" the arrow function):

For example:

// Function declaration
function createObject() {
  console.log('Inside `createObject`:', this.foo);
  return {
    foo: 42,
    bar: function() {
      console.log('Inside `bar`:', this.foo);
    },
  };
}

createObject.call({foo: 21}).bar(); // override `this` inside createObject

Here bar() will print 42 as it has it's own this. Now let's look at the behavior of arrow function in above scenario:

// Example using a arrow function
function createObject() {
  console.log('Inside `createObject`:', this.foo);
  return {
    foo: 42,
    bar: () => console.log('Inside `bar`:', this.foo),
  };
}

createObject.call({foo: 21}).bar(); // override `this` inside createObject

This will print 21 instead of 42, as arrow functions do not have their own this. Note: that this also means that is not possible to set an arrow function's this with .bind() or .call().

2) Arrow functions cannot be called with new


ES6 distinguishes between functions that are callable and functions that are constructable. If a function is constructable, it can be called with new, i.e. new User(). If a function is callable, it can be called without new (i.e. normal function call).

Functions created through function declarations / expressions are both constructable and callable. Arrow functions (and methods) are only callable.

If you are trying to call a non-callable function or to construct a non-constructable function, you will get a runtime error.

Kaushal28 commented 5 years ago

I've added initial draft above. Happy to address review comments!

nas5w commented 5 years ago

Thank you @Kaushal28, it might take me a couple days to get to my review but rest assured I will get to it and appreciate your contribution!

Kaushal28 commented 5 years ago

Any updates on this one?

nas5w commented 5 years ago

Sorry @Kaushal28, it has been a hectic week. This is still on my to-do list and I really do appreciate you suggesting this!