eval(fn)和eval(arrowFn)返回不同的值

时间:2017-05-05 12:59:33

标签: javascript ecmascript-6 eval arrow-functions

根据Mozilla docs为了使用eval执行某个功能,它必须包含在( )内,即如果您不使用它们,则将其视为一个字符串。

  

作为字符串定义函数的eval需要“(”和“)”作为前缀和后缀

当我执行普通函数时,它按预期返回undefined但不是ES6函数的情况。我的问题是ES6函数被javascript引擎或仅在eval函数中区别对待。

var fn = "function a(){}";
var es6fn = "()=>{}";

console.log(eval(fn)); // undefined
console.log(eval(es6fn)); // ()=>{}
console.log(typeof eval(es6fn)); // ()=>{} i.e. a function

4 个答案:

答案 0 :(得分:1)

让我们退后一步,看看这里到底发生了什么。我认为你误解了MDN试图提出的观点。在您的示例中执行的唯一功能是eval。提到的文档(...)不是用于在字符串中执行函数,而是用于更改如何评估函数定义

函数调用function a(){}(),但文档讨论将函数定义放在括号内:(function(){})

基本上有定义功能的主要方法:

  1. 功能声明

    function foo() {}
    
  2. 功能表达

    var foo = function() {}
    
  3. 箭头功能

    var foo = () => {}
    
  4. 要理解函数声明与函数表达式之间的区别,我们必须理解语句表达式之间的区别(声明基本上就像一个声明)。

    语句具有副作用并且产生ifforswitch等都是语句

    表达式是产生值的东西。例如。 5是一个数字 literal ,它产生值5. 5 + 3是一个表达式,用于计算两个文字的总和,即评估它将返回值8。

    函数声明就像一个声明。它本身并不产生值,但作为副作用,定义了一个变量,其值是一个函数(you can see in the specification that nothing happens when a function declaration is evaluated(它们已经在那时被处理过了))

    函数表达式非常相似,但是不是定义变量,而是评估它只会导致函数对象。

    这就是

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

    产生不同的结果。第一个被解释为函数声明。将创建变量a,但不会创建eval可以返回的值。在第二种情况下,分组运算符(...))强制将函数定义解释为函数表达式,这意味着生成一个值并返回eval

    现在关于箭头功能:这里没有歧义。箭头函数定义总是表达式,即评估它们总是产生一个值。

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

    总结

    虽然箭头函数和函数声明/表达式之间存在差异,但这种差异并不是您使用eval看到的结果的原因。这里的区别是因为eval声明/声明和表达式。

答案 1 :(得分:0)

在您的示例中,a被声明为命名函数。在第二种情况下,您只需编写一个lambda函数的表达式。请参阅herehere

如果您希望fn获得相同的效果,请执行

`console.log(eval("var a = function(){}"))`; //`function(){}`.

答案 2 :(得分:0)

首先,EcmaScript是"官方" JavaScript的名称。现在ES2015已经完成,它实际上只是成为大多数人的JavaScript v6。所以,这种差异并非来自不同的引擎。

不同行为的起源来自于在eval函数中写入的字符串的结果。第一个eval字符串的结果是一个函数定义,没有任何东西可以返回。另一方面,第二个eval正在评估lambda函数,因此eval的结果就是该函数。要清除此概念,您可以重写代码,如下所示:



<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet"/>



<div class="container">
  

  <ul class="nav nav-tabs">
    <li class="active"><a data-toggle="tab" href="#home">Home</a></li>
    <li><a data-toggle="tab" href="#menu1">Menu 1</a></li>
    <li><a data-toggle="tab" href="#menu2">Menu 2</a></li>
    <li><a data-toggle="tab" href="#menu3">Menu 3</a></li>
  </ul>

  <div class="tab-content">
    <div id="home" class="tab-pane fade in active">
      <h3>HOME</h3>
      <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.</p>
    </div>
    <div id="menu1" class="tab-pane fade">
      <h3>Menu 1</h3>
      <p>Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.</p>
    </div>
    <div id="menu2" class="tab-pane fade">
      <h3>Menu 2</h3>
      <p>Sed ut perspiciatis unde omnis iste natus error sit voluptatem accusantium doloremque laudantium, totam rem aperiam.</p>
    </div>
    <div id="menu3" class="tab-pane fade">
      <h3>Menu 3</h3>
      <p>Eaque ipsa quae ab illo inventore veritatis et quasi architecto beatae vitae dicta sunt explicabo.</p>
    </div>
  </div>
</div>
&#13;
&#13;
&#13;

您可以看到,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被定义为一个函数,您可以在第一个eval之后使用该函数。因此,第一个eval运行并返回到eval函数的返回值。

答案 3 :(得分:0)

文档中没有说明功能执行。这些函数不会被执行,除非它们像(() => {})()一样明确执行。

报价

  

作为字符串定义函数的eval需要“(”和“)”作为前缀和后缀

指的是将字符串解释为函数表达式而不是函数声明。

// 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';

箭头函数总是一个表达式,它不需要像逗号或括号那样的辅助结构来解释是一个表达式,这里有区别。