When should I use Arrow functions in ECMAScript 6?

后端 未结 9 1665
滥情空心
滥情空心 2020-11-21 05:53

The question is directed at people who have thought about code style in the context of the upcoming ECMAScript 6 (Harmony) and who have already worked with the language.

9条回答
  •  野趣味
    野趣味 (楼主)
    2020-11-21 06:14

    In addition to the great answers so far, I'd like to present a very different reason why arrow functions are in a certain sense fundamentally better than "ordinary" JavaScript functions. For the sake of discussion, let's temporarily assume we use a type checker like TypeScript or Facebook's "Flow". Consider the following toy module, which is valid ECMAScript 6 code plus Flow type annotations: (I'll include the untyped code, which would realistically result from Babel, at the end of this answer, so it can actually be run.)

    export class C {
      n : number;
      f1: number => number; 
      f2: number => number;
    
      constructor(){
        this.n = 42;
        this.f1 = (x:number) => x + this.n;
        this.f2 = function (x:number) { return  x + this.n;};
      }
    }

    Now see what happens when we use the class C from a different module, like this:

    let o = { f1: new C().f1, f2: new C().f2, n: "foo" };
    let n1: number = o.f1(1); // n1 = 43
    console.log(n1 === 43); // true
    let n2: number = o.f2(1); // n2 = "1foo"
    console.log(n2 === "1foo"); // true, not a string!

    As you can see, the type checker failed here: f2 was supposed to return a number, but it returned a string!

    Worse, it seems that no conceivable type checker can handle ordinary (non-arrow) JavaScript functions, because the "this" of f2 does not occur in the argument list of f2, so the required type for "this" could not possibly be added as an annotation to f2.

    Does this problem also affect people who don't use type checkers? I think so, because even when we have no static types, we think as if they're there. ("The first parameters must be a number, the second one a string" etc.) A hidden "this"-argument which may or may not be used in the function's body makes our mental bookkeeping harder.

    Here is the runnable untyped version, which would be produced by Babel:

    class C {
        constructor() {
            this.n = 42;
            this.f1 = x => x + this.n;
            this.f2 = function (x) { return x + this.n; };
        }
    }
    
    let o = { f1: new C().f1, f2: new C().f2, n: "foo" };
    let n1 = o.f1(1); // n1 = 43
    console.log(n1 === 43); // true
    let n2 = o.f2(1); // n2 = "1foo"
    console.log(n2 === "1foo"); // true, not a string!

提交回复
热议问题