【问题标题】:What are Gecko's Javascript interpreter engine semantics?Gecko 的 Javascript 解释器引擎语义是什么?
【发布时间】:2011-04-16 20:03:18
【问题描述】:

编辑

考虑到answer response below 关于 参考ECMAScript Language Specification - 11.13.2 Compound Assignment

考虑到这些原因,

javascript:
   o="";  o = o + (o+=1)    ; alert(o);
   o="";  o =     (o+=1) + o; alert(o);

不一样。从左到右的脚本评估存在时间语义问题(参考:ECMA spec. - The addition operator)。结果之一是+ 运算符不一定是可交换的。

这也可以通过以下方式看到:

javascript:
   o=1;  o = o + (o+=1)    ; alert(o);
   o=1;  o =     (o+=1) + o; alert(o);

javascript:
   o=" _ ";  o = o + (o+=1)    ; alert(o);
   o=" _ ";  o =     (o+=1) + o; alert(o);

懒惰的评估范式,被我错误地和不恰当地使用,从而产生了下面的问题,也是我个人作案手法的一个坏属性。


原帖

以下注意事项可能已经解决,但似乎没有。如果有,能否提供讨论链接?

Gecko Javascript 运行时引擎的正式指称语义是一个谜。 实证测试很累人,不可能穷尽。

  • 是否有权威的 正式规范或官方 准确定义 Gecko 的参考 解释 Javascript?

参考 ECMAScript Language Specification 似乎不够充分,尽管提供了类似这样的脚本的组合的可信度,

javascript: alert( function(){return {}}().life=42 )

在绑定值时具有此类构造的后续含义。

  • 是否有明确的范式 描述 Javascript 代码 对象的解释和 实例评估?

这将阐明调用(或者更确切地说是使用)需要、价值、参考、推理、名称等概念是否相关。也就是说,Javascript 是一个原型解释器,它为以下一些问题提供了隐含的含义。

预期的结果是什么:

javascript: o={n:0}; f=function(){o.n+=1; return 10};
   alert([
      o.n,            f(),
      o.n,       o.n+=f(),
      o.n, eval('o.n+=f()'), 
      o.n, eval('o.n+='+f()),
      o.n,
   ].join(",\t"));

?预测结果是否容易(正确!)?

这个问题有点修辞,因为它是专门用eval 设计的,以强制和强调解释的细微差别。是否可以使用 ECMAScript Language Specification 或其他文档来解决此脚本的评估(以及下面的问题)?

(顺便说一句,请考虑:

javascript: ra=[];
   alert([
      ra, ra[ra.length]=" partially defined.",
      ra, ra.push("\n RA is not shown"),
      ra, ra.reverse()[42],
   ].join(",\t\t"));

显示:

RA 未显示,部分定义。,部分定义。, RA 未显示,部分定义。,2, RA 未显示,部分定义。

ra 的部分评估与 o.n 的不相似!

以及以下比使用 o.n 更奇特的:

javascript: o=""; f=function(){o+=1; return 0};
   alert([
      o,          f(),
      o,       o+=f(),
      o, eval('o+=f()'), 
      o, eval('o+='+f()),
      o,
   ].join(",\t"));

显示:

, 0, 1, 10, 10, 100, 100, 10010, 10010

)

考虑以下脚本:

javascript:
   asn="\t\t and so now,\t o.n is "; nl="\n\n";
   o={}; f=function(){o.n+=1; return 10};
   alert(["Using:\n",window.navigator.userAgent,
   nl,"The function f() is:\n ",f,
   nl,"What the!!?!? \t\t\t\t\t\t\t initially \t\t o.n is ",          o.n = 0,
 nl,"Called as a procedure: \t\tf() is ", f(),                   asn, o.n,
nl,"but, instead of 12 \t\to.n+=f() is ", o.n+=f(),              asn, o.n,
     nl,"however eval'd\t\to.n+=f() is ", eval("o.n+="+f()),     asn, o.n,
    "!\n\nIt makes no functional difference if, instead of o.n, o['n'] is used.",
    "\nThe expected o.n evaluation sequence is 0, 1, (+1+10=) 12, (+1+10=) 23.",
    "\n_____ _____ _____ _____ _____ _____ _____ _____^^ missing in result",
  ].join(""));

Gecko 引擎输出:

使用: Mozilla/5.0(X11;U;Linux i686;en-US;rv:1.9.2.3) Gecko/20100423 Ubuntu/10.04(清醒)Firefox/3.6.3 函数 f() 是: 功能 () { o.n += 1; 返回 10; } 什么!!!!!最初 o.n 是 0 作为过程调用:f() 是 10,所以现在,o.n 是 1 但是,o.n+=f() 不是 12,而是 11,所以现在,o.n 是 11 但是 eval'd o.n+=f() 是 22,所以现在,o.n 是 22! 如果使用 o['n'] 而不是 o.n,则它在功能上没有区别。 预期的 o.n 评估序列是 0, 1, (+1+10=) 12, (+1+10=) 23。 _____ _____ _____ _____ _____ _____ _____ _____^^ 结果中缺失

【问题讨论】:

  • 我不是语言律师,但这似乎很有道理。 o.n 每次都被单独评估,为您提供当前存储在 o 的字段 n 中的整数 - 该字段稍后会被覆盖,之前存储在其中的整数不会发生变异。第二个示例将对同一对象的多个引用放入结果数组并同时对其进行变异,因此当您查看最终结果时,您会多次查看同一个对象。
  • 不知道为什么要多次喊出“Gecko”(实际上是 Mozilla 的 SpiderMonkey)。您为什么不在 Chrome 和 Internet Explorer 中进行测试?

标签: javascript language-lawyer evaluation


【解决方案1】:

JavaScript 具有在 ECMA 标准中明确说明的急切评估(按值调用)执行模型。所有这些问题都可以通过仔细阅读标准来解决。例如,结果是上面的11而不是12的原因在标准的11.13.2中有明确的说明。 o.n 在调用 f() 之前评估,而不是在步骤 2 指定之后评估。

【讨论】:

  • 非常感谢 - 让我思考 - 请参阅原始帖子之前的编辑。
  • 所有允许副作用的语言都有类似的问题。一些语言,例如 C 和 C++,甚至说评估的顺序是未定义的,允许实现根据给出的结果而变化。 JavaScript 不能,因此明确指定了顺序。在任何情况下,在具有副作用的程序语言中,应避免使副作用可见的结构,例如 o = o + (o+=1) 或更传统的 o = o + ++o。
  • 甚至是((o=1)+(++o)),而不是((++o)+(o=1))
  • 是的,在 C 或受 C 语言影响的语言中应该避免所有这些事情。它们在 Java、C# 和 JavaScript 中是标准化的,在 C 和 C++ 中未定义并且在所有这些中都很丑陋。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2010-09-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-05-21
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多