先看一个例子
var x = 'outer';
(function() {
var x = 'inner';
eval('console.log("direct call: " + x)');
(1,eval)('console.log("indirect call: " + x)');
})();
答案是:
direct call: inner
indirect call: outer
eval('1+1')是直接eval调用,而(1,eval)('1+1')不是。由于后者不是直接调用,因此它是间接eval调用。
( 1 , eval ) ( '1+1' )
|____| |_____| |_____|
常量 操作符 标识符
|_________________________|
表达式
|______________________________|
主要表达式
|______________________________| |________|
成员表达式 参数
|________________________________________________|
调用表达式
在上面的例子里,很显然参数(调用括号)之前的哪部分不只是由“eval”标识符组成。这是一个完整的其他类型的表达式,由逗号操作符,数字常量,然后才是"eval"标识符组成。1,eval - 基于逗号操作符运行的方式-仍然执行一个标准的内置的eval函数,不过整个表达式不再是直接调用了。因此它是 间接eval调用。
(1, eval)('...')
(eval, eval)('...')
(1 ? eval : 0)('...')
(__ = eval)('...')
var e = eval; e('...')
(function(e) { e('...') })(eval)
(function(e) { return e })(eval)('...')
(function() { arguments[0]('...') })(eval)
this.eval('...')
this['eval']('...')
[eval][0]('...')
eval.call(this, '...')
eval('eval')('...')
依据ES5,所有这些都是间接调用,且 应当在全局范围内执行执行代码。你是否注意到ES5定义说明调用表达式的eval应当执行标准的、内置的函数?这意味着根据上下文内容eval('1+1')必定不是直接调用。仅仅当eval真正地(不是重写或者隐含地)引用了标准的、内置的函数的时候,调用才被认为是直接调用。
eval = (function(eval) {
return function(expr) {
return eval(expr);
};
})(eval);
eval('1+1'); // 它看前来像直接调用,不过实际上是间接调用。
// 这是因为`eval`解析为定制的函数,而不是标准的、内置的函数。
eval('...')
(eval)('...')
(((eval)))('...')
(function() { return eval('...') })()
eval('eval("...")')
(function(eval) { return eval('...'); })(eval)
with({ eval: eval }) eval('...')
with(window) eval('...')
看前来相当的直白,难道不是吗?
不过等一下,为什么认为(eval)('...')和(((eval)))('...')是直接调用呢?当然,它们并不遵守我们前面所建立的特性 - 调用表达式内部的成员表达式内的有"eval"标识符。这儿到底发生什么呢?难道是eval两边的括号让它成为间接调用的吗?
这个有点微妙的问题的答案就在ES5直接调用定义的第一段里 - 是这样一个事实:调用表达式里的 "eval"应当是引用,而不是值。在程序执行期间,eval('1+1')表达式里的eval只不过是一个引用,而且需要计算出一个值。一旦计算完成,这个值(最可能)是标准的、内置的函数对象。在前面已经分析的(1,eval)('1+1')间接调用里所发生的是(1,eval)表达式计算出一个值,而不是一个引用。由于它计算出的
不是引用,所以不能认为它是直接eval调用。
但是(eval)('1+1')又如何呢?
认为(eval)是直接调用的原因是因为(eval)表达式仍然计算出的是一个引用,不是一个值。((eval)),(((eval)))等也是同样的。这种情况的出现是因为成组操作符-"("和")"-不能计算自身的表达式。如果传递引用给成组操作符-"("和")"-它仍然计算出一个引用,而不是一个值。
eval(); // <-- 调用括号左边的表达式 — "eval" — 计算出一个引用
(eval)(); // <-- 调用括号左边的表达式 — "(eval)" — 计算出一个引用
(((eval)))(); // <-- 调用括号左边的表达式 — "(((eval)))" — 计算出一个引用
(1,eval)(); // <-- 调用括号左边的表达式 — "(1, eval)" — 计算出一个值
(eval = eval)(); // <-- 调用括号左边的表达式 — "(eval = eval)" — 计算出一个值
如ECMAScript所说,这是因为两个操作符 - (例子(1,eval)里的)逗号操作符和(例子(eval=eval)里的)等号操作符-对它的操作数执行了GetValue。因此,(1,eval)和(eval = eval)计算出一个值,而eval 和 (eval)计算出的是一个引用。
现在希望已经弄清楚了(eval)('...')和(function(eval){ retuan eval('...')})(eval)是直接eval调用,而(1,eval)('...')和this.eval('...')不是直接调用的原因。
分享到:
相关推荐
公式操作、表达式动态语句,可以考虑使用 Eval Expression。 本文件给你无限使用的特权,基于netstand2.1制作,可以方便的用于netcore 3.1和net5中 需要下列包 <PackageReference Include="Microsoft.Extensions....
借助Faster R-CNN中voc_eval.py文件,测试YOLO测试数据集mAP等结果,博客见
java开源解析公式jar包 支持+ - * / abs % pow < > <> <= >= == && ||等很多 网址:https://eval.dev.java.net
Z.Expressions.Eval 4.0.68 包含.net3.1和 .net6的支持。不需要key,去除限制。
例: Expression e = new [removed]"1+2*((3+5)/10*5*4 +(1-2)/4)"); System.out.println(e.eval());//32.5 要求jdk1.6
powerdesigner125_eval.exe,powerdesigner125_eval.exe,powerdesigner125_eval.exe,powerdesigner125_eval.exe,powerdesigner125_eval.exe,powerdesigner125_eval.exe,powerdesigner125_eval.exe,powerdesigner125_...
下载iDRAC试用版许可证以便启用PowerEdge企业功能。 iDRAC9 试用
利用python计算darknet中yolo中的mAP值,此模块用用与加载的模块
能够进行绘制yolov3算法模型P-R曲线的脚本voc_eval.py,在python2环境下运行。
Codejock.ToolkitPro.MFC.Eval.17.3.0.part2
#include "stm32_eval_i2c_tsensor.h" #include "stm32_eval.h" #ifdef USE_STM32100E_EVAL #include "stm32100e_eval_lcd.h" #elif defined USE_STM3210E_EVAL #include "stm3210e_eval_lcd.h" #elif defined ...
S2T_eval.zip 防止文档被拷贝
CCKS2019赛题《面向金融的事件主题》数据,为了方便以后下载,所以上传到CSDN上,因为在查找数据的时候发现只有train数据集,而没有eval数据集,所以上传上去,方便以后学习的时候下载。
GD原厂移植的基于E230移植的常用OS,包含,FreeRTOS,rt-thread,ucos_ii,ucosiii
SQL2022-SSEI-Eval.exe
STM32100E-EVAL开发指南,该文档是STM32100E-EVAL的详细开发指南,可以配合库函数STM32F10x_StdPeriph_Lib_V3.5.0使用,
ide-eval-resetter-2.3.5-c80a1d.zipide-eval-resetter-2.3.5-c80a1d.zipide-eval-resetter-2.3.5-c80a1d.zipide-eval-resetter-2.3.5-c80a1d.zipide-eval-resetter-2.3.5-c80a1d.zipide-eval-resetter-2.3.5-c80a1d...
Z.Expression是一个开源的(OpenSource),可扩展的(Extensible),基于java语言开发的一个超轻量级(Super lightweight)的公式化语言解析执行工具包。
python 常用 示例 数据 train.csv eval.csv titanic.csv