eval(fn) and eval(arrowFn) returns different value

前端 未结 4 775
小鲜肉
小鲜肉 2021-01-26 09:13

As per the Mozilla docs in order to execute a function using eval it must be wrapped inside ( ) i.e. if you don\'t use them then it treate

4条回答
  •  闹比i
    闹比i (楼主)
    2021-01-26 09:40

    Lets take a step back and see what is actually going on here. I think you are misunderstanding the point MDN is trying to make. The only function that is executed in your example is eval. The (...) the documentation is mentioning are not for executing the function inside the string but for changing how the function definition is evaluated.

    A function call would function a(){}() but the docs talk about putting the function definition inside parenthesis: (function(){}).


    There are basically thee major ways to define functions:

    1. Function declaration

      function foo() {}
      
    2. Function expression

      var foo = function() {}
      
    3. Arrow function

      var foo = () => {}
      

    To understand the difference between a function declaration and a function expression, we have to understand the difference between statements and expressions (a declaration is basically like a statement).

    A statement is something that has side effects and does not produce a value. if, for, switch, etc are all statements.

    An expression is something that produces a value. E.g. 5 is a number literal that produces the value 5. 5 + 3 is an expression that computes the sum of the two literals, i.e. evaluating it will return the value 8.

    A function declaration is like a statement. It doesn't produce a value itself, but as a side effect, a variable is defined whose value is a function (you can see in the specification that nothing happens when a function declaration is evaluated (they have already been processed at that point)).

    A function expression is very similar, but instead of defining a variable, evaluating it simply results in the function object.

    And that is the reason why

    eval('function a() {}') // undefined, but a is defined as side effect
    eval('(function a() {})') // a function object
    

    produce different results. The first is interpreted as function declaration. A variable a will be created, but no value is created that eval could return. In the second case, the grouping operator ((...)) forces the function definition to be interpreted as a function expression, which means that a value is produced and return by eval.


    Now regarding arrow functions: There is no ambiguity here. Arrow function definitions are always expressions, i.e. evaluating them always produces a value.

    eval(`() => {}`) // a function object
    

    To sum up

    While there is a difference between arrow functions and function declarations/expressions, this difference is not the reason for the results you are seeing with eval. The difference here is because of evaling a statement/declaration and an expression.

提交回复
热议问题