编辑
考虑到下面的答案回应关于参考ECMAScript 语言规范 - 11.13.2 复合赋值
考虑为什么这些,
javascript:
o=""; o = o + (o+=1) ; alert(o);
o=""; o = (o+=1) + o; alert(o);
它们并不相同。从左到右的脚本评估存在时间语义问题(参考:ECMA规范 - 加法运算符)。其中一个后果是,+
运算符不一定是可交换的。
这也可以通过以下方式看出:
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语言规范或其他文档来解决?
(顺带一提:
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 (lucid) Firefox/3.6.3
函数f()是: function () { o.n += 1; return 10; }
What the!!?!? 最初 o.n为0
作为一个过程调用: f()是10 现在, o.n为1
但是,o.n+=f()是11 现在, o.n为11 而不是12
然而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
中的整数 - 该字段稍后将被覆盖,先前存储在其中的整数不会发生变化。第二个示例将几个对同一对象的引用放入结果数组中,并在此过程中对其进行了更改,因此当您查看最终结果时,您会多次查看同一对象。 - user395760