Cannot Access Component Variables in Subscribe whe

2019-09-10 13:29发布

问题:

Similar to this question but I already seem to have the selected answer. I have the following...

import {Component, OnDestroy} from '@angular/core';
import {MdIconRegistry} from "@angular2-material/icon/icon-registry";
import {MD_ICON_DIRECTIVES} from "@angular2-material/icon/icon";
import {ShowcaseCardComponent} from "./showcase-card/showcase-card.component";
import { WheelService } from "../../wheel/wheel.service";
@Component({
    selector: 'jg-showcase',
    template: String(require('./showcase.component.pug')),
    styles: [String(require('./showcase.component.styl'))],
    directives: [MD_ICON_DIRECTIVES, ShowcaseCardComponent],
    viewProviders: [MdIconRegistry]
})
export class ShowcaseComponent implements OnDestroy{
    currentCard: number = 0;
    subscription: any;
    cards = [
        {
            number: 0,
            color: "blue",
            content: "<h1>Card1</h1>"
        },
        {
            number: 1,
            content: "<h1>Card2</h1>"
        }
    ];
    constructor(wheelService: WheelService){
        this.subscription = wheelService.wheelEmitter.subscribe((data: any) => {
           if(data.direction > 0 && this.currentCard !== this.cards.length){
               this.currentCard++;
           }
           else if(this.currentCard){
               this.currentCard--;
           }
           console.log("Current Card "+this.currentCard);
        })
    };
    ngOnDestroy() {
        this.subscription.dispose();
    };
}

problem is that this is undefined in the inspector but I see the proper console.log...

Current Card 1
Current Card 2

Why is the console saying it is undefined

this.currentCard
VM10154:1 Uncaught TypeError: Cannot read property 'currentCard' of undefined(…)

回答1:

This has to do with how arrow function are implement in TS. this in arrow function is lexically inferred so it more in line with below code

function Person() {
  var self = this; // Some choose `that` instead of `self`. 
                   // Choose one and be consistent.
  self.age = 0;

  setInterval(function growUp() {
    // The callback refers to the `self` variable of which
    // the value is the expected object.
    self.age++;
  }, 1000);
}

So inside the arrow function it is not actually this but a context closer self. This may not be actual implementation but much closer to give you understanding of what is happening.

Now in Inspector when you type this it is outside the closer/ arrow function so will not get the correct context for this hence Inspector will show you either undefined or window or some global object

This should explain why your code is working but Inspector is not giving you expected value.

Protip see your transpiled JS how your arrow function is transforming.