Skip to content

Instantly share code, notes, and snippets.

@crutchcorn
Last active May 27, 2022 08:27
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save crutchcorn/a32eb1fe6d0b7b15b4f4045160445181 to your computer and use it in GitHub Desktop.
Save crutchcorn/a32eb1fe6d0b7b15b4f4045160445181 to your computer and use it in GitHub Desktop.
Explaination of `this` keyword in JavaScript through a series of Tweets
class Cup {
contents = "water";
consume() {
console.log(
"You drink the ",
this.contents,
". Hydrating!"
);
}
}
const cup = new Cup();
// This will log "You drink the water. Hydrating!"
cup.consume();
class Cup {
contents = "water";
consume = () => {
console.log(
"You drink the ", this.contents, ". Hydrating!"
);
}
}
class Bowl {
contents = "chili";
consume = () => {
console.log("You eat the ", this.contents, ". Spicy!");
}
}
cup = new Cup();
bowl = new Bowl();
cup.consume = bowl.consume;
// This will log "You eat the chili. Spicy!"
// Because `this` from an arrow function is not rebound
cup.consume();
// Even if we try to explictly bind to "cup"
// it won't work. Arrow functions can't be re-bound
cup.consume = bowl.consume.bind(cup);
@Component({
selector: 'paragraph',
template: `
<button #btn>Add one</button>
<p>Count is {{count}}</p>
`
})
class RenderParagraphComponent implements AfterViewInit, OnDestroy {
@ViewChild('btn') btn: ElementRef<HTMLElement>;
count = 0;
// No need to `bind` anymore!
// `this` will ALWAYS reference the component
addOne = () => {
this.count++;
}
ngAfterViewInit() {
this.btn.nativeElement
.addEventListener('click', this.addOne);
}
ngOnDestroy() {
this.btn.nativeElement
.removeEventListener('click', this.addOne);
}
}
class Cup {
contents = "water";
consume() {
console.log(
"You drink the ", this.contents, ". Hydrating!"
);
}
}
class Bowl {
contents = "chili";
consume() {
console.log(
"You eat the ", this.contents, ". Spicy!"
);
}
}
cup = new Cup();
bowl = new Bowl();
// This will log "You drank the water. Hydrating!""
cup.consume();
// This will log "You eat the chili. Spicy!"
bowl.consume();
class Cup {
contents = "water";
consume() {
console.log(
"You drink the ", this.contents, ". Hydrating!"
);
}
}
class Bowl {
contents = "chili";
consume() {
console.log(
"You eat the ", this.contents, ". Spicy!"
);
}
}
cup = new Cup();
bowl = new Bowl();
// This is assigning the `bowl.consume` message
cup.consume = bowl.consume;
// But using the `cup.contents` `this` scoping
cup.consume();
@Component({
selector: 'count-button',
template: `
<button #btn>Add one</button>
<p>Count is {{count}}</p>
`
})
class RenderParagraphComponent implements AfterViewInit {
@ViewChild('btn') btn: ElementRef<HTMLElement>;
count = 0;
addOne() {
// What is `this` being set to?
this.count++;
}
ngAfterViewInit() {
this.btn.nativeElement
.addEventListener('click', this.addOne);
}
// In prod, please do cleanup 😊
}
@Component({
selector: 'count-button',
template: `
<button #btn>Add one</button>
<button (click)="logButtonCount()">Click me</button>
`
})
class RenderParagraphComponent implements AfterViewInit {
@ViewChild('btn') btn: ElementRef<HTMLElement>;
addOne() {
// What is `this` being set to?
this.count++;
// Will output an HTMLElement instance of `button`
console.log(this);
}
ngAfterViewInit() {
// Otherwise `logButtonCount` will show `NaN`
this.btn.nativeElement.count = 0;
this.btn.nativeElement.addEventListener('click', this.addOne);
}
logButtonCount() {
// This increments every time `addOne` is ran
console.log(this.btn.nativeElement.count);
}
}
@Component({
selector: 'count-button',
template: `
<button #btn>Add one</button>
<button (click)="logButtonCount()">Click me</button>
`
})
class RenderParagraphComponent implements AfterViewInit {
@ViewChild('btn') btn: ElementRef<HTMLElement>;
// It's important to bind here, otherwise when we later
// go to `removeEventListener`, the reference won't be the same
addOne = function () {
this.count++;
}.bind(this);
ngAfterViewInit() {
this.btn.nativeElement.addEventListener('click', this.addOne);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment