-1

Below is my code:

let hat = {
    name: "Hat",
    price:"100",
    writeDetails: () =>
        console.log(`${this.name}: ${this.price}`)
};

//setup global variable
name = "global hat"
price = 999;

hat.writeDetails();

the output is undefined, undefined

why the global/window object is not injected in this?

adiga
  • 34,372
  • 9
  • 61
  • 83

5 Answers5

1

It is because of scoping, when arrow function is declared this here is scoped inside the function only. Use normal function for this.

9841pratik
  • 195
  • 8
0

Your problem is described in When (and why) you should use ES6 arrow functions — and when you shouldn’t section "Main benefit: No binding of ‘this’"

You can just avoid using the array function construct:

//writeDetails:     () => console.log(`${this.name}: ${this.price}`)
writeDetails: function() {console.log(`${this.name}: ${this.price}`)}
Michael Dreher
  • 1,369
  • 11
  • 17
0

An arrow function doesn’t have its own this; it inherits the this value of where it appears. In your case, that seems to not be the global object.

If you want writeDetails to act like a “normal method”, which the properties on hat seem to suggest, it shouldn’t be an arrow function:

let hat = {
    name: "Hat",
    price: "100",
    writeDetails() {
        console.log(`${this.name}: ${this.price}`);
    },
};

Then you can do the odd “global hat” thing with hat.writeDetails.call(this), if you want.

Ry-
  • 218,210
  • 55
  • 464
  • 476
0

Adding to the answers already given. You should read up on ES6 arrow functions and their use cases


Arrow functions are a shorthand method of declaring a function and binding it to the scope it is declared in.

Say a function declared like:

class C{
    foo = () => {
        console.log('foo')
    }
}

Roughly translates to something like:

 class C{
    foo(){
        console.log('foo')
    }
    this.foo = this.foo.bind(this)
 }

This causes the function to be binded to the scope it is declared in. In my example, it class C. this, if ever used in function foo will always point to the class object. In your case, it is declared inside a function, hence, its scope will always be the function itself.

If you declare a function normally without binding it, the this context passed to the function will be the context of the block from which you called it from. Say you called your unbinded function in class B.

In that case, the this passed to your function will be pointing to the object of class B

So your problem should be solved be declaring your function without a binding. Calling your function from outside any block or class will let your function inherit global scope.

Nabeel Mehmood
  • 378
  • 1
  • 5
0

The arrow functions were not intended to replace normal functions which use function keyword. For more details click here.

Here's the working alternative.

let hat = {
    nam: "Hat",
    _price: 100,
    priceIncTax: 100 * 1.2,
    set price(newPrice) {
        this._price = newPrice;
        this.priceIncTax = this._price * 1.2;
    },
    get price() {
        return this._price;
    },
    writeDetails(){
        console.log(`${this.nam}: ${this._price}, ${this.priceIncTax}`)}
};

hat.writeDetails();
mayank
  • 35
  • 1
  • 8