六个字符,带你领略JavaScript (js的艺术编写)
正文从这开始~
JavaScript是一门神奇且奇妙的编程语言,我们有时候用它来写一些看似疯狂的代码,但这些代码依然可被执行且运行结果十分有趣。JavaScript 试图帮助我们将一些数据类型转化为我们所认为的数据类型。
如果我们定义一个字符串常量,它会假设我们希望添加的是文本形式,所以 JavaScript 会把它转化为字符串类型。
如果我们加上『+』或『-』前缀,JavaScript 会认为我们需要它以数值形式表示,如果条件允许,它甚至会把字符串也转换为数值类型。
如果我们添加「表示否定的符号」,JavaScript 会将它转换为布尔类型。
我们可以利用 " [ " ," ] " ," ( " ," ) " ," ! " 和 " + " 六个字符做一些神奇的事情,如果你现在使用电脑浏览器阅读这篇文章,你可以在阅读的同时,打开浏览器的控制台,复制代码,粘贴并执行。
让我们从基础开始,先记住以下黄金法则:
「 ! 」后面接的字符会被转换为布尔值。
「 + 」后面接的字符会被转换为数值。
「 [ ] 」后面接的字符会被转换为字符串。
来看下面的例子:
你需要知道,字符串可以像数组一样,以方括号下标的形式从字符串检索特定字母:
你也应该知道,我们也可以将多个字符连接成字符串,然后将整个表达式转换成数值:
好的,我们继续把他们结合在一起来得到字母「 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 代码中,并执行它们,这是一个相当罕见的攻击方式。
一些人可能会提到代码混淆,但事实上,这将是一种更好的代码混淆方式。
六个字符,带你领略JavaScript (js的艺术编写)的更多相关文章
- JavaScript基本知识点——带你逐步解开JS的神秘面纱
JavaScript基本知识点--带你逐步解开JS的神秘面纱 在我们前面的文章中已经深入学了HTML和CSS,在网页设计中我们已经有能力完成一个美观的网页框架 但仅仅是网页框架不足以展现出网页的魅力, ...
- js实现过滤重复字符和重复数组-javascript技巧
js实现过滤重复字符 <script type="text/javascript"> <!-- String.prototype.noRepeatStr=func ...
- 【HANA系列】【第六篇】SAP HANA XS使用JavaScript(JS)调用存储过程(Procedures)
公众号:SAP Technical 本文作者:matinal 原文出处:http://www.cnblogs.com/SAPmatinal/ 原文链接:[HANA系列][第六篇]SAP HANA XS ...
- 【转】关于URL编码/javascript/js url 编码/url的三个js编码函数
来源:http://www.cnblogs.com/huzi007/p/4174519.html 关于URL编码/javascript/js url 编码/url的三个js编码函数escape(),e ...
- 关于URL编码/javascript/js url 编码/url的三个js编码函数
关于URL编码/javascript/js url 编码/url的三个js编码函数escape(),encodeURI(),encodeURIComponent() 本文为您讲述关于js(javasc ...
- Linux内核分析(六)----字符设备控制方法实现|揭秘系统调用本质
原文:Linux内核分析(六)----字符设备控制方法实现|揭秘系统调用本质 Linux内核分析(六) 昨天我们对字符设备进行了初步的了解,并且实现了简单的字符设备驱动,今天我们继续对字符设备的某些方 ...
- JavaScript(js)/上
JavaScript(js) ECMA-----定义的基础语法 DOM------document object model BOM------Browser object model Jav ...
- Atitit. Java script 多重多重catch语句的实现and Javascript js 异常机制
Atitit. Java script 多重多重catch语句的实现and Javascript js 异常机制 1. 语法错误(ERROR)和运行期错误(Exception) 1 2. 错误类型判断 ...
- [javascript]JS如何获取当前时间戳
[javascript]JS如何获取当前时间戳 一.总结 一句话总结:var timestamp = Date.parse(new Date()); 结果是带三位毫秒的,再除个1000取整即可 1.j ...
随机推荐
- linux下 C++ 读取mat文件 MATLAB extern cyphon scipy 未完待续
1.使用Matlab的C扩展,需要用户安装matlab. g++ -L/media/exsoftware/MATLAB/R2013b/bin/glnxa64 -Wl,-rpath,/media/exs ...
- 使用 Portable Class Library(可移植类库)开发 Universal Windows App
今天在这里跟大家聊聊关于 Windows Universal 应用夸平台的问题,首先Universal Windows App的定义相信大家已经有所了解了(如果你是一个刚刚接触 Universal A ...
- pidgin修改来消息字体大小
vi ~/.gtkrc-2.0写入如下内容设置自己想要的字体大小 style "imhtml-fix"{ font_name = "Sans 14"} w ...
- QT在windows下实现截屏操作并保存为png图片
QPixmap originalPixmap = QPixmap::grabWindow(QApplication::desktop()->winId()); QString format = ...
- HP P1008打印机如何打印特殊纸张
一.问题的提出 HP P1008中间有一个进纸槽,这是干什么的? 二.问题的分析 查说明,说这个进纸槽是叫做优先进纸槽,用于各种非常规的纸张的打印. 三.问题的解决 弄一张特殊尺寸的纸张,打开要编辑的 ...
- eclipse项目导入androidstudio
1.添加build.gradle buildscript { repositories { jcenter() } dependencies { classpath 'com.android.tool ...
- 蓝凌表单的表体调用Javascript
应用场景:像请假类表单会在从表输入开始时间.结束时间等字段 需求1:客户希望根据开始.结束时间自动计算小时数 解决方法: 1.主表单增加一行,设三个字段[开始时间合计].[结束时间合计].[开始结束时 ...
- 单链表List的C实现
头文件———————————————————————————————— //单链表的实现 #ifndef _LIST_H_ #define _LIST_H_ #include <stdlib.h ...
- 固态硬盘寿命实测让你直观SSD寿命!--转
近年来,高端笔记本及系列上网本越来越多的采用固态硬盘来提升整机性能,尽管众所周知固态硬盘除 了在正常的使用中带来更快速度的体验外,还具有零噪音.不怕震动.低功耗等优点,但大家对固态硬盘的寿命问题的担忧 ...
- Mina、Netty、Twisted一起学(二):TCP消息边界问题及按行分割消息
在TCP连接开始到结束连接,之间可能会多次传输数据,也就是服务器和客户端之间可能会在连接过程中互相传输多条消息.理想状况是一方每发送一条消息,另一方就立即接收到一条,也就是一次write对应一次rea ...