Arrow VS Classic Method in Es6 Class

Arrow vs classic method in ES6 class

The feature you are using is not part of ES6. It's the class fields proposal. It allows you to initialize instance properties without having to write a constructor. I.e. your code:

class MyClass {

myMethod = () => {
this.myVariable++;
}

}

is exactly the same as

class MyClass {

constructor() {
this.myMethod = () => {
this.myVariable++;
};
}

}

And this also shows you what the difference is between a normal class method an a method created via a class field:

  • A normal method is shared between all instances of the class (it is defined on the prototype)
  • A "class field method" is created per instance

So all the same as reasons as presented in Use of 'prototype' vs. 'this' in JavaScript? apply, but in short:

  • Use "class field methods" if you need a method per instance. Such is the case for event handlers that need to access the current instance. Access to this also only works if you are using an arrow function.
  • Use normal class methods in all other cases.

ES6 functions, arrow functions and 'this' in an ES6 class

It's important to know that this syntax:

class A {
method = () => {}
}

is just syntactic sugar for creating an instance method in the class constructor:

class A {
constructor() {
this.method = () => {}
}
}

Note: This syntax is not an official part of the JavaScript language yet (currently in stage 3) so you must use a transpiler like Babel to handle it.

The value of this within method is the class A because that is what this points to in the constructor (since arrow functions inherit the context from the scope they are defined in):

class A {  constructor() {    this.method = () => this;  }}
const instance = new A();console.log(instance.method() === instance); // true

Are arrow functions faster (more performant, lighter) than ordinary standalone function declaration in v8?

V8 developer here. Arrow functions are (mostly) just "syntactic sugar" for conventional function declarations. There is no performance difference.

Methods in ES6 objects: using arrow functions

Arrow functions are not designed to be used in every situation merely as a shorter version of old-fashioned functions. They are not intended to replace function syntax using the function keyword. The most common use case for arrow functions is as short "lambdas" which do not redefine this, often used when passing a function as a callback to some function.

Arrow functions cannot be used to write object methods because, as you have found, since arrow functions close over the this of the lexically enclosing context, the this within the arrow is the one that was current where you defined the object. Which is to say:

// Whatever `this` is here...
var chopper = {
owner: 'Zed',
getOwner: () => {
return this.owner; // ...is what `this` is here.
}
};

In your case, wanting to write a method on an object, you should simply use traditional function syntax, or the method syntax introduced in ES6:

var chopper = {
owner: 'Zed',
getOwner: function() {
return this.owner;
}
};

// or

var chopper = {
owner: 'Zed',
getOwner() {
return this.owner;
}
};

(There are small differences between them, but they're only important if you use super in getOwner, which you aren't, or if you copy getOwner to another object.)

There was some debate on the es6 mailing list about a twist on arrow functions which have similar syntax but with their own this. However, this proposal was poorly received because that is mere syntax sugar, allowing people to save typing a few characters, and provides no new functionality over existing function syntax. See the topic unbound arrow functions.

What is the difference (if any) between the different function declarations within JavaScript objects?

The "class style function" (shorthand method) is very similar to a regular function. The only difference is that it can't be used as a constructor (i.e. called with new), and because of that it doesn't have a prototype property. As for arrow functions, see Arrow function vs function declaration / expressions: Are they equivalent / exchangeable?. In a nutshell, arrow functions don't bind their own this and arguments, and can't be used with new.

Is it down to personal preference? Or do the inner workings change?

In ES6+ there's no reason to use the traditional function syntax in objects, because the shorthand methods syntax is simpler and safer, because if you accidentally try to use a method as a constructor, you'll get an error. As for arrow functions, you can use them only if you don't need to access the object using this.

Are 'Arrow Functions' and 'Functions' equivalent / interchangeable?

tl;dr: No! Arrow functions and function declarations / expressions are not equivalent and cannot be replaced blindly.

If the function you want to replace does not use this, arguments and is not called with new, then yes.


As so often: it depends. Arrow functions have different behavior than function declarations / expressions, so let's have a look at the differences first:

1. Lexical this and arguments

Arrow functions 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):

// Example using a function expression
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


Related Topics



Leave a reply



Submit