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

前端 未结 4 774
小鲜肉
小鲜肉 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条回答
  • 2021-01-26 09:28

    In your example, a is declared as it's a named function. In the second case, you just write an expression which is a lambda function. See here and here.

    If you want to get the same effect for fn, do

    `console.log(eval("var a = function(){}"))`; //`function(){}`.
    
    0 讨论(0)
  • 2021-01-26 09:34

    First of all, EcmaScript is the "official" name for JavaScript. Now that ES2015 is finalised, it effectively just becomes JavaScript v6 to most people. So, this difference does not come from the different engin.

    The origin of the different behavior comes from the result of the string which is written in the eval function. the result of the first eval string is a function definition and there is not anything to return. On the other side, the second eval is evaluating a lambda function, so the result of the eval is that function. To clear this concept, you can rewrite the code like the following:

    var fn = "function a(){ return 1;}";
    var es6fn = "()=>{}";
    
    console.log(eval(fn)); // undefined
    console.log(eval(es6fn)); // ()=>{}
    console.log(typeof eval(es6fn)); // ()=>{} i.e. a function
    console.log(a()); // call the a() function

    As, you can see, the a() is defined as a function, and you can use the function after the first eval. So, the first eval is run and all back to the return value for eval function.

    0 讨论(0)
  • 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.

    0 讨论(0)
  • 2021-01-26 09:42

    The documentation says nothing on function execution. The functions won't be executed, unless they are executed explicitly like (() => {})().

    The quote

    eval as a string defining function requires "(" and ")" as prefix and suffix

    refers to interpreting the string as function expression rather than function declaration.

    // will throw SyntaxError
    // because function declaration requires a name
    typeof eval('function (){}'); 
    
    typeof eval('function a(){}') === 'undefined';
    typeof eval('(function a(){})') === 'function';
    typeof eval('null, function a(){}') === 'function';
    typeof eval('()=>{}') === 'function';
    

    Arrow function is always an expression, it doesn't need auxiliary constructions like comma or parentheses to interpret is an expression, here is the difference.

    0 讨论(0)
提交回复
热议问题