Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
265 views
in Technique[技术] by (71.8m points)

javascript - What is the difference between class method vs. class field function vs. class field arrow function?

What is the difference between class method, class property which is a function, and class property which is an arrow function? Does the this keyword behave differently in the different variants of the method?

class Greeter {
  constructor() {
    this.greet();
    this.greet2();
    this.greet3();
  }

  greet() {
    console.log('greet1', this);
  }

  greet2 = () => {
    console.log('greet2', this);
  }

  greet3 = function() {
    console.log('greet3', this);
  }
}
      
let bla = new Greeter();

This is the resulting JavaScript when transpiled from TypeScript.

var Greeter = /** @class */ (function () {
function Greeter() {
    var _this = this;
    this.greet2 = function () {
        console.log('greet2', _this);
    };
    this.greet3 = function () {
        console.log('greet3', this);
    };
    this.greet();
    this.greet2();
    this.greet3();
}
Greeter.prototype.greet = function () {
    console.log('greet1', this);
};
return Greeter;
}());
var bla = new Greeter();

My TypeScript version is 3.4.5.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

There are differences between all 3 versions. This differences are in 3 areas:

  1. Who is this at runtime
  2. Where the function is assigned
  3. What is the type of this in typescript.

Lets start with where they work just the same. Consider this class, with a class field:

class Greeter {
  constructor(private x: string) {
  }
  greet() {
    console.log('greet1', this.x);
  }

  greet2 = () => {
    console.log('greet2', this.x);
  }

  greet3 = function () {    
    // this is typed as any 
    console.log('greet3', this.x);
  }
}

let bla = new Greeter(" me");

With this class all 3 function calls will print as expected: 'greet* me' when invoked on bla

bla.greet()
bla.greet2()
bla.greet3()

Who is this at runtime

Arrow functions capture this from the declaration context, so this in greet2 is always guaranteed to be the class instance that created this function. The other versions (the method and function) make no such guarantees.

So in this code not all 3 print the same text:

function call(fn: () => void) {
  fn();
}

call(bla.greet) // greet1 undefined 
call(bla.greet2) //greet2 me
call(bla.greet3) // greet3 undefined

This is particularly important when passing the function as an event handler to another component.

Where the function is assigned

Class methods (such as greet) are assigned on the prototype, field initializations (such as greet2 and greet3) are assigned in the constructor. This means that greet2 and greet3 will have a larger memory footprint as they require an allocation of a fresh closure each time Greeter is instantiated.

What is the type of this in typescript.

Typescript will type this as an instance of Greeter in both the method (greet) and the arrow function (greet2) but will type this as any in greet3. This will make it an error if you try to use this in greet3 under noImplictAny

When to use them

  1. Use the method syntax if this function will not be passed as an event handler to another component (unless you use bind or something else to ensure this remains the instance of the class)

  2. Use arrow function syntax when your function will be passed around to other components and you need access to this inside the function.

  3. Can't really think of a good use case for this, generally avoid.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...