正文从这开始~编程
JavaScript是一门神奇且奇妙的编程语言,咱们有时候用它来写一些看似疯狂的代码,但这些代码依然可被执行且运行结果十分有趣。JavaScript 试图帮助咱们将一些数据类型转化为咱们所认为的数据类型。数组
若是咱们定义一个字符串常量,它会假设咱们但愿添加的是文本形式,因此 JavaScript 会把它转化为字符串类型。浏览器
若是咱们加上『+』或『-』前缀,JavaScript 会认为咱们须要它以数值形式表示,若是条件容许,它甚至会把字符串也转换为数值类型。编程语言
若是咱们添加「表示否认的符号」,JavaScript 会将它转换为布尔类型。函数
咱们能够利用 " [ " ," ] " ," ( " ," ) " ," ! " 和 " + " 六个字符作一些神奇的事情,若是你如今使用电脑浏览器阅读这篇文章,你能够在阅读的同时,打开浏览器的控制台,复制代码,粘贴并执行。工具
让咱们从基础开始,先记住如下黄金法则:测试
「 ! 」后面接的字符会被转换为布尔值。code
「 + 」后面接的字符会被转换为数值。对象
「 [ ] 」后面接的字符会被转换为字符串。ip
来看下面的例子:
你须要知道,字符串能够像数组同样,以方括号下标的形式从字符串检索特定字母:
你也应该知道,咱们也能够将多个字符链接成字符串,而后将整个表达式转换成数值:
好的,咱们继续把他们结合在一块儿来获得字母「 a 」:
有趣!
因此,咱们利用上述字符的一些简单组合就能够获得「 true 」和「 false 」中的字母,好比「 t 」「 r 」「 u 」「 e 」「 f 」「 a 」「 l 」「 s 」。那么咱们能够获得其余字母吗?
固然,咱们能够经过「 [ 」「 ] 」的简单组合来获得「undefined」,也就是说利用刚提到的黄金法则,咱们又获得了「 d 」「 i 」「 n 」三个字母。
目前为止,咱们用已得到的字母就能够拼出「 fill 」「 filter 」 和「 find 」单词,固然还有一些其余的单词。但还需注意, 这些单词都具备数组的方法。这意味着他们是数组对象的一部分,能够直接调用数组实例,如:[2,1].sort()。
如今,咱们要了解 JavaScript 另外一个重要特性:一个对象的属性能够经过点符号.或方括号[]访问。上述数组方法是数组对象自己的属性,咱们可使用方括号代替点,来调用这些方法。
因此说 [2,1]["sort"]() 和 [2,1].sort() 是等效的。
来让咱们继续深刻尝试,看看用数组方法调用还会发生什么。咱们能够试着用刚才获得的字母拼写出单词,并将这些单词做为方法调用。看下面的例子:
这样会获得:
咱们能够再次使用咱们的黄金法则,将这个方法头转换为字符串:
到目前为止,咱们就又获得了「c」「o」「v」「(」「)」「{」「}」「[」「]」这些字母或者符号。
因为咱们新得到了「c」和「o」两个字母,就能够和之前的字母组合成「constructor」(构造函数)单词。
constructor 方法被全部 JavaScript 对象所共有,并且它会返回构建该对象的函数。
接下来让咱们把已经获得的对象的构造函数,以字符串形式展示出来:
这样一来,咱们又获得了「B」「N」「S」「A」「m」「g」「y」这些字母,咱们把它们添加到咱们的『字母库』。如今咱们能够用字母库中的字母,构造一个可用方括号的函数「toString」。
咱们能够这样调用它:
咱们已经能够利用黄金法则,将任何咱们想要的东西转换成字符串。但咱们要怎么使用呢?
好的,我如今告诉你,「Number」类型的「toString」方法有一个称为「radix」(基数)的秘密的论点。它规定一个数值在转换为字符串以前先进行基数换算,像这样:
可是为何基数最大为16?正常来讲最大为36。但这样一来,咱们就获得了包括从「 0 - 9 」和「 a - z 」全部数字和字符。
干得漂亮!
可是其余的字符该怎么办呢?好比标点字符和大写字符?咱们接着向下摸索!
因为你的 JavaScript 代码执行环境不一样,不能肯定它是否能够成功访问到你预约义的对象或数组。若是你在浏览器中执行,它可能会访问到遗留的 HTML包装器方法。
比方说,「bold」是一个包装在 <b> 标签中的字符串方法。
这样一来,咱们又获得了「 < 」「 > 」和「 / 」字符。
可能你之前据说过「escape」函数。它主要做用是将一个字符串,转换成一种浏览器友好的 URL 格式,而且可以被常见的浏览器识别和解析。
为了达成最终目标,这个函数的功能十分重要,因此咱们要努力实现并合理利用它。咱们虽然能用「字母库」中的字母拼写出「escape」单词,但咱们该如何将它真正的执行出来?
「escape」是一个全局做用域下的函数,就是说它不属于咱们目前为止处理过的任何函数类型。
那么任意函数的构造函数是什么呢?
答案是:「 function Function() { [native code] } 」。
利用这一点,咱们能经过一串代码来构造一个实际功能的函数。
也能获得:
咱们只需在结束执行时弹出「 ( ) 」,就能够当即调用并执行「 alert 」函数。
是的,咱们如今能够编译执行字符串构成的代码了。
因此接下来,咱们像下面所示,使用「 escape 」函数:
若是咱们在「 escape 」函数中传入「 < 」字符,咱们会获得「 %3C 」。哈哈,这样咱们又获得了字母「 C 」,若是你想拼出咱们缺乏的其余单词,那么「 C 」字母是很是必要的。
利用字母「 C 」,咱们能够写出「 fromCharCode 」函数了,这个函数的功能是将咱们给定的十进制数转换为「 Unicode 」码。它是「 String 」对象的一部分,像咱们之前同样,调用它的构造函数获得咱们所需的字符:
咱们利用 「 Unicode Lookup: convert special characters 」工具可以很容易地找到任何字符的十进制表示形式。
嘿,伙计!咱们终于大功告成!
如今,咱们可以只用这六个字符获取任何一个其余字符,咱们能将他们拼接起来,拼接出一行行代码,咱们也能成功执行它们。
这意味着在 JavaScript 中,咱们仅仅用「 [ 」「 ] 」「 ( 」「 ) 」「 + 」和「 ! 」六个字符,就能够完成 图灵完备测试( Turing completeness )!!
你想证明一下?在你的控制台中运行文章最后的代码吧~
这几个字符有很大做用吗?
事实并不是如此,不久前 eBay 网利用这些作了一些很差的事情,它容许一些卖家将这些字符以某种形式嵌入店铺主页的 JavaScript 代码中,并执行它们,这是一个至关罕见的攻击方式。
一些人可能会提到代码混淆,但事实上,这将是一种更好的代码混淆方式。