eval(fn) 和 eval(arrowFn) returns 不同的值
eval(fn) and eval(arrowFn) returns different value
根据 Mozilla docs 为了使用 eval
执行一个函数,它必须被包裹在 (
)
里面,即如果你不使用它们那么它被视为字符串。
eval as a string defining function requires "(" and ")" as prefix and suffix
当我执行正常功能时,它 returns undefined
如预期的那样,但在 ES6 功能的情况下却不是。我的问题是 javascript 引擎或仅在 eval 函数中对 ES6 函数进行不同处理。
var fn = "function a(){}";
var es6fn = "()=>{}";
console.log(eval(fn)); // undefined
console.log(eval(es6fn)); // ()=>{}
console.log(typeof eval(es6fn)); // ()=>{} i.e. a function
在您的示例中,a
被声明为一个命名函数。在第二种情况下,您只需编写一个表达式,它是一个 lambda 函数。参见 here and here。
如果你想为 fn
获得相同的效果,请执行
`console.log(eval("var a = function(){}"))`; //`function(){}`.
首先,EcmaScript 是 JavaScript 的 "official" 名称。现在 ES2015 已经完成,对大多数人来说它实际上变成了 JavaScript v6。因此,这种差异并非来自不同的引擎。
不同行为的起源来自于 eval 函数中写入的字符串的结果。第一个 eval 字符串的结果是一个函数定义,return 没有任何内容。另一方面,第二个 eval 正在评估 lambda 函数,因此 eval 的结果就是该函数。要清楚这个概念,你可以像下面这样重写代码:
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
如您所见,a()
被定义为一个函数,您可以在第一次 eval 之后使用该函数。因此,第一个 eval 是 运行 并且全部返回到 eval 函数的 return 值。
文档没有提及函数 执行。这些函数不会被执行,除非它们像 (() => {})()
.
这样明确地执行
引用
eval as a string defining function requires "(" and ")" as prefix and suffix
指将字符串解释为函数表达式而不是函数声明。
// 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';
箭头函数始终是一个表达式,它不需要逗号或括号等辅助结构来解释是一个表达式,这是不同之处。
让我们退后一步,看看这里到底发生了什么。我认为您误解了 MDN 试图表达的观点。在您的示例中执行的唯一函数是 eval
。文档中提到的 (...)
不是为了在字符串中执行函数,而是为了改变 函数定义的计算方式 .
函数调用会 function a(){}()
但文档讨论将函数定义 放在 括号内:(function(){})
.
函数的定义主要有以下几种方式:
函数声明
function foo() {}
函数表达式
var foo = function() {}
箭头函数
var foo = () => {}
要理解函数声明和函数表达式之间的区别,我们必须理解之间的区别statements 和 expressions(声明基本上就像一个语句)。
语句是具有副作用并且不会产生价值的东西。 if
、for
、switch
等都是语句.
表达式是产生值的东西。例如。 5
是一个数字 literal 产生值 5。5 + 3
是一个计算两个文字之和的表达式,即计算它会 return 值 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
可以 return 的值。在第二种情况下,分组运算符((...)
)强制将函数定义解释为函数表达式,这意味着eval
.
产生了一个值 return
现在关于箭头函数:这里没有歧义。箭头函数定义总是表达式,即对它们求值总是产生一个值。
eval(`() => {}`) // a function object
总结
虽然箭头函数和函数 declarations/expressions 之间存在差异,但这种差异并不是您在 eval
中看到的结果的原因。这里的区别是因为 eval
ing 一个 statement/declaration 和一个表达式。
根据 Mozilla docs 为了使用 eval
执行一个函数,它必须被包裹在 (
)
里面,即如果你不使用它们那么它被视为字符串。
eval as a string defining function requires "(" and ")" as prefix and suffix
当我执行正常功能时,它 returns undefined
如预期的那样,但在 ES6 功能的情况下却不是。我的问题是 javascript 引擎或仅在 eval 函数中对 ES6 函数进行不同处理。
var fn = "function a(){}";
var es6fn = "()=>{}";
console.log(eval(fn)); // undefined
console.log(eval(es6fn)); // ()=>{}
console.log(typeof eval(es6fn)); // ()=>{} i.e. a function
在您的示例中,a
被声明为一个命名函数。在第二种情况下,您只需编写一个表达式,它是一个 lambda 函数。参见 here and here。
如果你想为 fn
获得相同的效果,请执行
`console.log(eval("var a = function(){}"))`; //`function(){}`.
首先,EcmaScript 是 JavaScript 的 "official" 名称。现在 ES2015 已经完成,对大多数人来说它实际上变成了 JavaScript v6。因此,这种差异并非来自不同的引擎。
不同行为的起源来自于 eval 函数中写入的字符串的结果。第一个 eval 字符串的结果是一个函数定义,return 没有任何内容。另一方面,第二个 eval 正在评估 lambda 函数,因此 eval 的结果就是该函数。要清楚这个概念,你可以像下面这样重写代码:
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
如您所见,a()
被定义为一个函数,您可以在第一次 eval 之后使用该函数。因此,第一个 eval 是 运行 并且全部返回到 eval 函数的 return 值。
文档没有提及函数 执行。这些函数不会被执行,除非它们像 (() => {})()
.
引用
eval as a string defining function requires "(" and ")" as prefix and suffix
指将字符串解释为函数表达式而不是函数声明。
// 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';
箭头函数始终是一个表达式,它不需要逗号或括号等辅助结构来解释是一个表达式,这是不同之处。
让我们退后一步,看看这里到底发生了什么。我认为您误解了 MDN 试图表达的观点。在您的示例中执行的唯一函数是 eval
。文档中提到的 (...)
不是为了在字符串中执行函数,而是为了改变 函数定义的计算方式 .
函数调用会 function a(){}()
但文档讨论将函数定义 放在 括号内:(function(){})
.
函数的定义主要有以下几种方式:
函数声明
function foo() {}
函数表达式
var foo = function() {}
箭头函数
var foo = () => {}
要理解函数声明和函数表达式之间的区别,我们必须理解之间的区别statements 和 expressions(声明基本上就像一个语句)。
语句是具有副作用并且不会产生价值的东西。 if
、for
、switch
等都是语句.
表达式是产生值的东西。例如。 5
是一个数字 literal 产生值 5。5 + 3
是一个计算两个文字之和的表达式,即计算它会 return 值 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
可以 return 的值。在第二种情况下,分组运算符((...)
)强制将函数定义解释为函数表达式,这意味着eval
.
现在关于箭头函数:这里没有歧义。箭头函数定义总是表达式,即对它们求值总是产生一个值。
eval(`() => {}`) // a function object
总结
虽然箭头函数和函数 declarations/expressions 之间存在差异,但这种差异并不是您在 eval
中看到的结果的原因。这里的区别是因为 eval
ing 一个 statement/declaration 和一个表达式。