根据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
答案 0 :(得分:1)
让我们退后一步,看看这里到底发生了什么。我认为你误解了MDN试图提出的观点。在您的示例中执行的唯一功能是eval
。提到的文档(...)
不是用于在字符串中执行函数,而是用于更改如何评估函数定义。
函数调用function a(){}()
,但文档讨论将函数定义放在括号内:(function(){})
。
基本上有定义功能的主要方法:
功能声明
function foo() {}
功能表达
var foo = function() {}
箭头功能
var foo = () => {}
要理解函数声明与函数表达式之间的区别,我们必须理解语句和表达式之间的区别(声明基本上就像一个声明)。
语句具有副作用并且不产生值。 if
,for
,switch
等都是语句。
表达式是产生值的东西。例如。 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函数的表达式。请参阅here和here。
如果您希望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;
您可以看到,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';
箭头函数总是一个表达式,它不需要像逗号或括号那样的辅助结构来解释是一个表达式,这里有区别。