我正在观看2011年https://www.youtube.com/watch?v=M3uWx-fhjUc
的Google I / O演示文稿在第39:31分钟,Michael显示了闭包编译器的输出,它看起来像下面的代码。
我的问题是这段代码的确切内容(方式和原因)
// Question #1 - floor & random? 2147483648?
Math.floor(Math.random() * 2147483648).toString(36);
var b = /&/g,
c = /</g,d=/>/g,
e = /\"/g,
f = /[&<>\"]/;
// Question #2 - sanitizing input, I get it...
// but f.test(a) && ([replaces]) ?
function g(a) {
a = String(a);
f.test(a) && (
a.indexOf("&") != -1 && (a = a.replace(b, "&")),
a.indexOf("<") != -1 && (a = a.replace(c, "<")),
a.indexOf(">") != -1 && (a = a.replace(d, ">")),
a.indexOf('"') != -1 && (a = a.replace(e, """))
);
return a;
};
// Question #3 - void 0 ???
var h = document.getElementById("submit-button"),
i,
j = {
label: void 0,
a: void 0
};
i = '<button title="' + g(j.a) + '"><span>' + g(j.label) + "</span></button>";
h.innerHTML = i;
修改
感谢您提供富有洞察力的答案。我仍然很好奇编译器抛出脚本顶部的随机字符串生成的原因。当然必须有充分的理由。任何人???
答案 0 :(得分:2)
如有疑问,请查看其他基地。
2147483648(基数10)= 0x80000000(基数16)。所以它只是制作一个32位带符号int
范围内的随机数。 floor
正在将其转换为实际的int,然后toString(36)
将其转换为36个字符的字母,即0-9(10个字符)加上a-z(26个字符)。
第一行的最终结果是一串随机数字和字母。将会有6个(36 ^ 6 = 2176782336),但第一个不会像其他人一样随机(在字母表中不会迟到)。编辑:阿德里安在他的回答中正确地解决了这个问题。第一个字母可以是36个字符中的任何一个,但是稍微不太可能是Z.其他字母对较低值的偏差较小。
对于问题2,如果你的意思是a = String(a);
,那么是,确保a
是一个字符串。这也是对编译器的一个暗示,如果它能够将它转换为机器代码,它可以做出更好的优化(我不知道它们是否可以用于字符串)。
编辑:好的,你澄清了这个问题。 f.test(a) && (...)
是使用短路评估的常见技巧。它实际上是在说if(f.test(a)){...}
。不要在实际代码中使用它,因为它使其可读性较差(尽管在某些情况下它更具可读性)。如果你想知道test
,那就是正则表达式。
对于问题3,这对我来说也是新的!但请看这里:What does `void 0` mean?(快速谷歌搜索。原来它很有趣,但很奇怪)
答案 1 :(得分:2)
有许多不同的问题集于一身,但考虑到问题标题,我只关注第一个:
Math.floor(Math.random() * 2147483648).toString(36);
实际上,这不会任何 - 因为值被丢弃而不是分配。但是,这样做的想法是生成一个介于0和2 ^ 31 - 1之间的数字,并在基数36中返回它。
Math.random()返回一个从0(包括)到1(不包括)的数字。然后将其乘以2 ^ 31以产生所述范围。 .toString(36)
然后将其转换为基数36,由0到9表示,后跟A到Z。
最终结果范围从0到(我相信)ZIK0ZI。
至于为什么它首先在那里......好吧,检查幻灯片。此行显示在顶部。虽然这是纯粹的猜想,但我实际上怀疑代码被裁剪成可见的东西,而且它上面有一些东西被分配给它。
答案 2 :(得分:2)
1)我不知道1号的重点是什么。
2)看起来确保任何符号都正确地转换为相应的HTML entities,所以基本上清理输入以确保它是HTML安全的
3)void 0
本质上是一种非常安全的方法,可以确保它返回undefined
。由于javascript中的实际undefined
关键字是可变的(即可以设置为其他关键字),因此假设undefined
实际上等于您期望的未定义值并不总是安全的。
答案 3 :(得分:2)
1)此代码从Closure Library中提取。此代码只是创建随机字符串。在以后的版本中,它被替换为简单地创建一个大的随机整数,然后连接成一个字符串:
'closure_uid_' + ((Math.random() * 1e9) >>> 0)
这个简化版本更容易让Closure Compiler删除,所以你不会像之前那样看到它的剩余部分。具体来说,编译器假定“toString”没有参数不会导致可见的状态更改。但是,它没有对带参数的toString调用做出相同的假设。您可以在此处阅读有关编译器假设的更多信息:
https://code.google.com/p/closure-compiler/wiki/CompilerAssumptions
2)在某些时候,有人确定在根据假设大多数字符串不需要转义的“替换”调用之前测试可能需要替换的字符更快。
3)正如其他人所说的那样,void运算符总是返回undefined,而“void 0”只是写“undefined”的合理方式。在正常使用中它几乎没用。