101

In ES6, both of these are legal:

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

and, as shorthand:

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

Is it possible to use the new arrow functions as well? In trying something like

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

or

var chopper = {
    owner: 'John',
    getOwner: () => (this.owner)
};

I get a error messages suggesting that the method does not have access to this. Is this just a syntax issue, or can you not use fat-pipe methods inside of ES6 objects?

davidtbernal
  • 12,404
  • 9
  • 41
  • 58
fox
  • 11,694
  • 20
  • 47
  • 76
  • 12
    One of the biggest points of the new function syntax was that it treats `this` differently. It's defined by the lexical environment in which the function was created, which means the `this` value where you create the `chopper` variable will be the `this` value of the function. In other words, it won't be referencing the `chopper` object. –  Jun 28 '15 at 03:00
  • got it, is there any way to rewrite this function so that it refers to `owner` inside chopper? – fox Jun 28 '15 at 03:07
  • 1
    While using the fat arrow syntax? Only if you alter the `this` value by first creating the `chopper` object, then doing the assignment in a function that has `this` pointing to that object. This can be accomplished pretty cleanly with a constructor function. –  Jun 28 '15 at 03:09
  • If you wanted to write that up with an example in answer form, I'd be happy to mark it as the correct answer. – fox Jun 28 '15 at 03:11
  • 1
    This demo will run in Firefox. Chrome doesn't have it yet. http://jsfiddle.net/bfyarxfe/ –  Jun 28 '15 at 03:12
  • Ask the guy below to give you a demo so you can accept his answer. –  Jun 28 '15 at 03:17
  • ok, out of curiosity, why won't the following work?: http://jsfiddle.net/bfyarxfe/1/ – fox Jun 28 '15 at 03:27
  • 2
    @fox, you must use 'use strict' on that jsfiddle. – Walter Chapilliquen - wZVanG Jun 28 '15 at 03:32
  • like this? http://jsfiddle.net/bfyarxfe/2/ – fox Jun 28 '15 at 03:35
  • chopper is `undefined`, since you also are in strict mode, variables must be declared before `var chopper = ...`. Again, sorry and excuse my english. – Walter Chapilliquen - wZVanG Jun 28 '15 at 03:37
  • 1
    @fox: It works fine in a supported environment. Firefox doesn't yet have complete support. Try it in [Continuum](http://benvie.github.io/continuum/) and `console.log()` the result of the method call. It works. –  Jun 28 '15 at 03:39
  • @wZVanG: Strict mode would make it fail with an error because of the missing `var`. It would work without strict mode if Firefox had support. –  Jun 28 '15 at 03:40
  • See also [How does the “this” keyword in Javascript act within an object literal?](http://stackoverflow.com/q/13441307/1048572) - the `this` in an arrow function always is the same `this` as if you replaced the arrow function with the keyword. – Bergi Jun 05 '16 at 21:49
  • Mozilla docs says **Does not have its own bindings to this or super, and should not be used as methods** [Mozilla Arrow function documentation](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/Arrow_functions) – Mohamed Yaseen Sep 26 '20 at 15:20

6 Answers6

171

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.

T.J. Crowder
  • 879,024
  • 165
  • 1,615
  • 1,639
  • If I'm reading this correctly, it seems to suggest that the mailing list deprioritizes syntactic sugar, even if it would lead to greater uniformity/readability of code. As it stands, it's much more challenging to use the fat-arrow functions in an OOP context under ES6 than, say, under coffeescript. – fox Jun 28 '15 at 04:25
  • As I understand it, syntactic sugar **is** considered a valid reason for considering language extensions, but as you say with a lower priority--in other words, the bar is higher for such proposals. –  Jun 28 '15 at 05:07
  • A bit confused. From what I understand for the function keyword notation, this points to the context of execution, where it is called, not where it is defined. https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/this . In the example above, can you really relay on on `this.owner` the be equal to the value that is defined on the chopper object? – Ben Carp Jan 20 '21 at 15:48
13

In this line getOwner: () => this.owner should be:

var chopper = {
    owner: 'John',
    getOwner: () => this.owner
}; //here `this` refers to `window` object.

You would have to declare this into a function:

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

Or:

var chopperFn = function(){

    this.setOwner = (name) => this.owner = name;
    Object.assign(this,{
        owner: 'Jhon',
        getOwner: () => this.owner,
    })

}

var chopper = new chopperFn();
console.log(chopper.getOwner());
chopper.setOwner('Spiderman');
console.log(chopper.getOwner());
FZs
  • 11,931
  • 11
  • 28
  • 41
  • 1
    I'm getting an error here: `"TypeError: Cannot read property 'owner' of undefined\n at Object.chopper.getOwner` – fox Jun 28 '15 at 03:04
  • I see, it is the correct use, however the method esta always returns window Object. You would have to declare `this` within a function. – Walter Chapilliquen - wZVanG Jun 28 '15 at 03:10
  • 2
    `this` doesn't necessarily refer to `window`. It refers to whatever the current value of `this` is in the enclosing environment, which may or may not be `window`. Maybe that's what you meant. Just want to make sure he understands it isn't some default value. –  Jun 28 '15 at 03:18
  • @torazaburo That is fine for me, I tried it, `this` now refers to class – Walter Chapilliquen - wZVanG Jun 28 '15 at 03:39
  • 2
    What you have written is equivalent to, but more verbose than, simply writing `var chopperFn = function() { this.owner = 'Jhon'; this.getOwner = () => this.owner; }`. –  Jun 28 '15 at 03:42
  • Yes. You can also do, but in this case we will assign the properties on an object `{prop: ...}`, like OP example. – Walter Chapilliquen - wZVanG Jun 28 '15 at 03:46
1

A quick tip that I follow to use arrow functions.

  • Use non-arrow functions for methods that will be using object.method() syntax. (Those are functions that will receive meaningful this value from their caller.)
  • Use arrow function for almost everything else.
1

Another tip, in strict mode, this still refers to Window instead of undefined.

  (() => {
    "use strict";
    console.log(this); // window
  })();

  (function () {
    "use strict";
    console.log(this); // undefined
  })();
Vimniky Luo
  • 126
  • 1
  • 6
0

This inside arrow function doesn't reflect context of the object. Instead it gives the context where the object method is called.

Check this, This gives some insight about when to use arrow and when not. https://dmitripavlutin.com/when-not-to-use-arrow-functions-in-javascript/

prabushitha
  • 1,180
  • 8
  • 13
0

If you have to use arrow function, you can change this to chopper,

var chopper = {
  owner: "John",
  getOwner: () => chopper.owner
};

Although this is not best practice, when you change the object name, you have to change this arrow function.

foxiris
  • 1,906
  • 21
  • 25