JavaScript Quine揭秘:如何让程序输出自身源代码?
介绍
如何写一段javascript程序,输出自身的源代码?这个问题非常有意思,大家不妨先尝试一下,反正在尝试了半个小时之后,我果断放弃了。
这种能输出自身的程序在英文里被称为quine。
准备知识
其实要实现这样一段程序,至少要掌握javascript中两个重要的知识点:
- IIFE
- toString()方法
关于IIFE,之前的文章已经做过详细的介绍,这里就不再赘述了,感兴趣的同学可以先去看一下。
关于toString()方法,相信大家也不陌生,但是你可知道对于一个函数来说,调用toString()方法意味着什么?
没错,调用一个函数的toString()方法会返回这个函数的源代码。
function foo() {
console.log('hello world')
}
console.log(foo.toString()) // 输出foo的源代码
第一个例子
有了上面的知识储备,我们可以动手写一下了,首先写一个函数foo,在函数体内调用console.log(foo.toString())输出函数的源代码。
function foo() {
console.log(foo.toString())
}
但是这只是函数定义,并未执行,所以需要在函数定义之后调用它。
function foo() {
console.log(foo.toString())
}
foo() // 调用函数,输出源代码
运行上面的代码,输出的结果如下所示,可以看到最后的调用语句foo()并没有打印出来。
function foo() {
console.log(foo.toString())
}
这不符合我们的要求,所以考虑去掉调用语句,将函数改为IIFE的形式
(function foo() {
console.log(foo.toString())
})()
运行上面的代码,输出的结果如下,最外层的()和末尾调用函数的()没有打印出来,这也不符合我们的要求。
function foo() {
console.log(foo.toString())
}
改造一下内部的console.log,将两组括弧也输出来。
(function foo() {
console.log('(' + foo.toString() + ')()')
})()
这回结果终于正确了,我们进一步改造,使用+拼接字符串时,js会自动将+另一侧的操作数转换为字符串,所以我们可以把toString()省略掉。
(function foo() {
console.log('(' + foo + ')()')
})()
再增加点神秘感,将foo换成$
(function $() {
console.log('(' + $ + ')()')
})()
运行结果如下:
(function $() {
console.log('(' + $ + ')()')
})()
这就是一个简单的javascript quine了。
最短的例子
在上面的例子中,为了便于观察结果,使用了console.log输出了源代码,实际上我们可以直接返回源代码,这样就可以省略掉console.log语句。
(function $() {
return '(' + $ + ')()'
})()
根据前面两篇文章学到的IIFE的知识,我们使用IIFE的箭头函数形式。下面这段代码定义一个箭头函数并将其赋值给变量$,然后立即执行这个函数。
($ = () => {
return '(' + $ + ')()'
})()
但是它的执行结果中没有包含$,我们加上$
($ = () => {
return '($ =' + $ + ')()'
})()
根据箭头函数的规则,如果返回值只有一行,那么可以省略掉大括号{}和return关键字,所以我们可以进一步简化为
($ = () => '($ =' + $ + ')()')()
再将字符串拼接操作改为ES6的模板字符串形式:
($ = () => `($ = ${$})()`)()
最后去掉空格,得到如下代码。
($=()=>`($=${$})()`)()
这就是史上最短的javascript quine了。需要注意的是,上面的代码需要在浏览器的控制台中运行,如果在IDE中运行,代码格式化工具可能会将代码格式化,导致结果不正确。
你还能想到其他办法吗?欢迎在评论区分享你的想法。
JavaScript Quine揭秘:如何让程序输出自身源代码?的更多相关文章
- 创建ArcGIS API for JavaScript的第一个示例程序
原文:创建ArcGIS API for JavaScript的第一个示例程序 在上一篇博客中已经介绍了如何搭建ArcGIS API for JavaScript开发环境,如果您还没有搭建好开发环境的话 ...
- javascript两行代码按指定格式输出日期时间
javascript两行代码按指定格式输出日期时间,具体看代码: function date2str(x,y) { var z ={y:x.getFullYear(),M:x.getMonth()+1 ...
- PHP程序输出日历
以下代码只是简单实现日历的效果和逻辑思路,没有使用类封装,权当抛砖引玉,有兴趣的朋友可以封装起来,方便调用. <?php /** * PHP利用时间函数输出日历 * Rain.zen $ int ...
- Bootstrap3 代码-程序输出
通过 <samp> 标签来标记程序输出的内容. This text is meant to be treated as sample output from a computer prog ...
- java笔记--重定向输出流实现程序输出到日志
重定向输出流实现程序输出到日志 --如果朋友您想转载本文章请注明转载地址"http://www.cnblogs.com/XHJT/p/3877248.html "谢谢-- 利用Sy ...
- 双缓冲解决控制台应用程序输出“闪屏”(C/C++,Windows)
使用 C 语言编写游戏的小伙伴们想必起初都要遇到这样的问题,在不断清屏输出数据的过程中,控制台中的输出内容会不断地闪屏.出现这个问题的原因是程序对数据处理花掉的时间影响到了数据显示,或许你可以使用局部 ...
- 用VSCode终端实现重定向比较程序输出和正确输出
在刷 OJ 题目或者进行编程考试或比赛时,经常需要对编写好的程序进行测试,即运行编写好的程序,输入样例输入或者自己编写的输入数据,查看程序输出结果和样例输出或者正确输出是否一致.这种方法有很多弊端,当 ...
- cmake指定程序输出目录和库文件输出目录和拷贝文件
概述 本文样式环境: win10+cmake 3.18 本文将介绍使用CMAKE配置项目输出目录和 LIbrary项目的输出目录 本文将介绍 cmake的file函数的基础用法之拷贝文件 重点, 这些 ...
- 【转】【译】JavaScript魔法揭秘--探索当前流行框架中部分功能的处理机制
推荐语: 今天推荐一篇华为同事的同事翻译的一篇文章,推荐的主要原因是作为一个华为员工居然晚上还能写文章,由不得小钗不佩服!!! 其中的jQuery.angular.react皆是十分优秀的框架,各有特 ...
- javascript quine
javascript有一些奇怪的性质,恩,比如说,非常容易写一个quine,即自己输出自己代码的东西. function a(){console.log(a.toString()+";a() ...
随机推荐
- FireDAC开发DataSnap应用系统【2】-使用TFDJSONDatasets功能
类别 说明 TFDJSONDatasets FireDAC使用JSONDataSet,其中可包括多个DataSet对象 TFDJSONDataSetsWriter 把TDataSet写入TFDJSON ...
- 使用Python+SymPy计算无穷级数
引言 在数学中,级数是指由数列的无限项组成的求和表达式.无穷级数的求和是一个非常重要且具有挑战性的数学问题,特别是在信号处理.物理学和工程学等领域.今天,我们将介绍如何利用 Python 中的 Sym ...
- JMeter提取响应结果保存到本地总结
1.说明 本次实验以登录接口为例提取响应结果中的uid和ticket参数并保存到csv文件 2.脚本结构 说明: 1)本次实验的在于BeanShell后置处理程序的编写,登录接口参数传递之前有些总结, ...
- java.security.provider.getservice blocked
JDK版本: JDK8u192 bug: https://bugs.openjdk.org/browse/JDK-8206333 堆栈: "Common-Business-Thread-57 ...
- 还有的时候,会遇到DataGrid里面嵌套DataGrid(重叠嵌套),然后里面的鼠标滚轮无法响应外面的滚动,为此记录下解决方案
与上一篇区别在于,详情里面的模板通常是通用的,被定义在样式文件中,被重复使用,因此无法为其添加后台代码,如果能添加后台代码,请翻阅第一篇:所以需要用到命令的方式来辅助事件的抛出,当然还可以利用第三方库 ...
- K8s容器运行时,移除Dockershim后存在哪些疑惑?
K8s容器运行时,移除Dockershim后存在哪些疑惑? 大家好,我是秋意零. K8s版本截止目前(24/09)已经发布到了1.31.x版本.早在K8s版本从1.24.x起(22/05),默认的容器 ...
- hadoop部署安装(四)KAFKA+SCALA
3.8 配置scala 下载,解压 wget https://downloads.lightbend.com/scala/2.13.0-M5/scala-2.13.0-M5.tgz tar -zxvf ...
- 环境搭建: Vue3+Echarts5+vue-eharts + 移动端rem适配
对于数据可视化的最后一站, 就是移动数据报表的展示, 毕竟手机端的适普性, 便携性, 灵活性更高. 包括我自己也是更多在移动端进行轻量办公. 而用主流的商业BI平台在PC端的体验基本可打80分, 而在 ...
- LR梯度下降法MSE演练
同步进行一波网上代码搬砖, 先来个入门的线性回归模型训练, 基于梯度下降法来, 优化用 MSE 来做. 理论部分就不讲了, 网上一大堆, 我自己也是理解好多年了, 什么 偏导数, 梯度(多远函数一阶偏 ...
- 集成学习双雄:Boosting和Bagging简介
在机器学习的世界里,集成学习(Ensemble Learning)是一种强大的技术,它通过组合多个模型来提高预测性能. 集成学习通过组合多个基学习器的预测结果,获得比单一模型更优秀的性能.其核心思想是 ...