为我的博客做了一个很有 geek 风格的关于页面。
运行下面 javascript 代码,可以看到我的信息。
(+[[]+(1<<1<<1<<1)+(1^1<<1)+(1<<1>>1)+(-~1<<1<<1)+(1.1>>1.1)+(11>>>1)])[[(!!/-/+{})[111^111]+[[]+{}][!1&.1][1|1>>1|1]]+([111/[]+[]][+(1>1)][([]+{})[11-1>>1]+[[],[]+{}+[]][[]+1][1]+(/^/[1]+[])[1|1>>1|1]+[{},1e1,!{}+[]][1+1][1<<1^1]+(11/!{}+{})[~1+1e1+~1]+[!!{}+{}][[]&111][1&1]+(/^/[111]+[])[11^11]+[{},[{}]+{},1][1+[]][11-~1+11>>1]+(!!1+{})[1&1>>1]+([]+{1:1}+[])[1|1]+[[]+!!1][111>>>111][1<<1>>1]]+[])[([]+![111])[1|1<<1|1]+[/=/,[]+[][11]][1|[]][1>>1]+([{}]+{})[1+!![1]]+[1,!1+/~/][1%11][1^1<<1]+(111/[]+{})[~1+1e1+~1]+[!!/-/+/-/][111%111][+!!1]]((~1+1e1+1)+((!1&.1)==([]+/-/[(!![111]+{})[1^1]+(!![1]+[])[1<<1^1]+(!{}+{})[1^1<<1]+(!![1]+/-/)[+(1>1)]])[+(1>1)]),1-~1<<1)](~1-~1e1<<1<<1)+":"+(([]===[])+/-/)[5]+(([]===[])+/-/)[5]+(+[[]+(1e1>>1)+(~1+1e1+~1)+(!1&.1)+(111%11)+(1+1<<1)+(1<<1^11>>1)+(1<<1<<1)+(~1+1e1+1)+(+(1>1))+(+[])+(~1-1+11)+(-~1<<1<<1)+(1-~1<<1)+(~1+1e1)])[[(!!/-/+[])[11&[]]+[[]+{11:11}+[]][111>>111][1+[]]]+([11/!1+/1/][1&1>>1][([{}]+{})[1e1>>1|1]+[[],[]+{111:111}+[]][1|1][111%11]+([]+[][11])[1<<1>>1]+[{},1e1,!/~/+{}][1<<1^1>>1][1<<1^1]+([]+11/!{})[~1+1e1+~1]+[!![111]+[]][1%1][1&1]+([]+[][111])[.1^!1]+[{},[]+{},1][111%11][11-~1+11>>1]+([]+!!1)[111>>>111]+([]+{}+[])[[]+1]+[!!1+[]][1^1][111%11]]+[])[(!1+{})[1^1<<1]+[/=/,[]+/^/[11]][1|[]][11.11>>11.11]+([]+{}+[])[~~(1.1+1.1)]+[1,!{}+/~/][1][1|1<<1]+(1/!{}+[])[~1+1e1+~1]+[!![1]+{}][111.111>>111.111][1+[]]]((11^1<<1)+((1>>1)==([]+/-/[(!!/-/+/-/)[+(111>111)]+(!![11]+[])[1-~1]+(![11]+{})[1|1<<1|1]+(!!{}+[])[11%11]])[111.111>>111.111]),11+1>>1)](~1-~1e1<<1<<1)+"."+(+[[]+([]+1)+(1-~1<<1)+(1+1<<1)+(1|1<<1)+(1<<1<<1<<1)])[[(!!1+{})[!1&.1]+[[]+{}+[]][1&[]][1+[]]]+([11/[]+{}][+(111>111)][([{}]+[{}])[1e1>>1]+[[],[]+{}][[]+1][+!!1]+(/^/[111]+/&/)[1&1]+[{},1e1,!1+[]][1<<1][1^1<<1]+(111/!{}+/1/)[~1+1e1+~1]+[!!/-/+[]][11>>11][1|1]+([][1]+/&/)[1.1>>1.1]+[{},[{}]+{},1][~~1][1+1e1+1]+([]+!!1)[1^1]+([]+{})[1&1]+[!!1+{}][!1&.1][1|[]]]+[])[([]+!1)[1|1<<1|1]+[/=/,[]+/^/[11]][111%11][11.11>>11.11]+([{}]+[{}])[~~(1.1+1.1)]+[1,[]+!/~/][1|1>>1|1][1^1<<1]+([]+11/[])[11+1>>1]+[!!/-/+{}][+(1<1)][~~1]]((1e1-1)+((+[])==([]+/-/[(!!1+[])[!1&.1]+(!!/-/+/-/)[1|1<<1|1]+(!1+{})[1<<1^1]+(!![1]+/-/)[11>>11]])[111^111]),-~11>>1)](~1-~1e1<<1<<1)
如何实现的呢?
@OKter 说是 ASCII 码拼接。到底是不是呢?
第一步
先来个简单的,就以 justjavac
为例吧。首先我们要输出 j
。
下面这段代码可以输出 j
:
(1+{})[4]
解释:代码 1+{}
的结果是 "1[object
Object]"
, 显然,我们得到了一个包含 j 的字符串。但为什么会如此奇怪呢?毕竟我们都期望 1+{}
的结果应该是 1。
对象加法
有下面这样的一个加法操作。
value1 + value2
在计算这个表达式时,内部的操作步骤是这样的 (§11.6.1):
-
将两个操作数转换为原始值 (以下是数学表示法的伪代码,不是可以运行的 JavaScript 代码):
prim1 := ToPrimitive(value1) prim2 := ToPrimitive(value2)
PreferredType
被省略,因此Date
类型的值采用String
,其他类型的值采用Number
。 -
如果 prim1 或者 prim2 中的任意一个为字符串,则将另外一个也转换成字符串,然后返回两个字符串连接操作后的结果。
-
否则,将 prim1 和 prim2 都转换为数字类型,返回他们的和。
更多详细内容参考
由于字符串可以当作数组一样取里面的元素,于是 (1+{})[4]
就得到了 j。
第二步
既然我们得到了 j,那下一步就是 u 了。我们还是按照这个思路,哪个字符串里面还有 u 呢? 在 javascript 中确实有这么一个特殊的值,含有 u: "undefined",思来想去,可以使用这段代码:
/1/[1]+[]
分开解释:
-
/1/
是一个正在表达式 -
当他后面跟上 [] 时,被强制转换成了数组,然后去取里面的元素(第二个元素),得到的结果是 undefined(注意:是 undefined 值,不是字符串)
-
把 undefined 转换成字符串,在这里我们把它和数组相加。
呵呵,上面使用正在表达式 /1/
有点儿卖弄的嫌疑,其实用 1[1]
就够了。
为了更有 geek 感,可以多出现 0 和 1。通过 /1+/[+0]+[+1]
我们可以得到字符串 "undefined1"。
使用数组操作符把我们想要的 u 提取出来, (/1+/[+0]+[+1])[0]
。
现在我们已经得到了字符串 "ju" 了。按照这种方法,我们可以得到其他的字符串。没有做不到的,只有想不到的。
问题来了
用这种方法能拼出所有的字符吗? @长夜 则提出了更深的问题: “可以拼中文吗?”
@TODO 待续……
大功告成
当我们得到了所有的字符串,就可以使用 + 号把他们连接起来。 你以为这就完了吗?当然远远没有,我们应该让我们的代码更 Cool,更有 geek 范。