原文自转->这里
早上看了justjavac大大的一篇文章:javascript 的 quine 顺序升级版,了解了一下所谓quine顺序的观点:
一个 quine 是一个计算机顺序,它不接收任何输入,且唯一的输出就是自身的源代码。
以为挺有意义的,因而盘算自身用js写一个尝尝。
起首肯定输出体式格局为掌握台,即经由过程console.log
输出。
为有(guang)趣(gao)起见,预备从一个“打印本站域名”的“分外功用”最先:
console.log("perichr.org")
这个敕令能够在掌握栏打印出一行perichr.org
。接下来我预备一步一步革新这个敕令,直至杀青quine的目的。
起首试着打印上面这个敕令:
console.log('console.log("perichr.org")')
如许就在掌握栏打印了一行console.log("perichr.org")
。注重到源码里外用了差别的引号,这是为了躲避转义符。
对了,别忘了须要实行自身,那末有:
console.log("perichr.org");console.log('console.log("perichr.org")')
很好,如许即实行了“分外功用”,又打印了自身的源代……不对!压根没有打印自身的源代码对吧!
从简朴的入手,不斟酌打印完全源代码,先想想要如何能在实行一个功用的同时打印功用代码呢?打印的是字符串,实行的是js源码……想到什么了?对了,eval
!
p='console.log("perichr.org")';eval(p);console.log(p)
很好,此次圆满地打印了perichr.org
和console.log("perichr.org")
。要注重的是,这里的变量p
没有做声明,严厉形式下是通不过的哟!
不过这还远远不够!来做一点小调解:
p='console.log("perichr.org");console.log(p)';eval(p)
发明了吗?此次输出了perichr.org
和console.log("perichr.org");console.log(p)
!进化了!接下来先讨个巧,应用 赋值表达式返回右值 的小技能来简化一下代码,毕竟代码越精简心理压力越小嘛……
eval(p='console.log("perichr.org");console.log(p)')
接下来怎样办呢……来对比下上面的源码和输出的代码:console.log("perichr.org");console.log(p)
,实在已很接近了有木有!输出码就是缺少了头eval(p='
和尾')
!来,补上!
eval(p='console.log("perichr.org");console.log("eval(p=\'"+p+"\')")')
在补的时刻就应该已注重到了一个题目:转义符!这里已没法防止转义符了!来看看输出的代码:eval(p='console.log("perichr.org");console.log("eval(p='"+p+"')")')
真好,已非常接近了对吧!但照样有一点小题目:没错,转义符!输出时源码中的\'
被转义成了'
!怎样办?那就要把文本中的'
反转义为\'
!怎样转?能够运用"'".replace(/'/g,"\\'")
这类体式格局。斟酌到文本要在p
的赋值时转义,那末就须要手动反转义为:'.replace(/\'/g,"\\\\\'")'
。接下来把它插进去源码中:
eval(p='console.log("perichr.org");console.log("eval(p=\'"+p.replace(/\'/g,"\\\\\'")+"\')")')
等等……彷佛有什么不对?我适才是否是把一大波 有效的反斜杠 到场源代码了?要知道,这货也是会被转义的啊!!怎样办?好嘛,来革新下反转义代码,这回单引号和反斜杠都要反转义一下:.replace(/[\\']/g,"\\$&")
,这里的$&
是指返回婚配字符串。手动反转义:.replace(/[\\\\\']/g,"\\\\$&")
,再来一次:
eval(p='console.log("perichr.org");console.log("eval(p=\'"+p.replace(/[\\\\\']/g,"\\\\$&")+"\')")')
在掌握台试一试……胜利!圆满!强力!分毫不差地返回了自身!使命圆满完成!
如何,看起来很嵬峨上的东西,实在入门很简朴吧?
有人问,费力心计写这么个东西,有啥意义?嘛,这个天下不是为了“某些人所谓的意义”而存在的。天下存在的意义在于“天下存在”这个征象自身;我折腾这个东西的意义也就在于“折腾代码”这件事自身。我以为我获得了一些有意义的东西。你说呢?