介绍

如何写一段javascript程序,输出自身的源代码?这个问题非常有意思,大家不妨先尝试一下,反正在尝试了半个小时之后,我果断放弃了。

这种能输出自身的程序在英文里被称为quine

准备知识

其实要实现这样一段程序,至少要掌握javascript中两个重要的知识点:

  1. IIFE
  2. toString()方法

关于IIFE,之前的文章已经做过详细的介绍,这里就不再赘述了,感兴趣的同学可以先去看一下。

JavaScript 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揭秘:如何让程序输出自身源代码?的更多相关文章

  1. 创建ArcGIS API for JavaScript的第一个示例程序

    原文:创建ArcGIS API for JavaScript的第一个示例程序 在上一篇博客中已经介绍了如何搭建ArcGIS API for JavaScript开发环境,如果您还没有搭建好开发环境的话 ...

  2. javascript两行代码按指定格式输出日期时间

    javascript两行代码按指定格式输出日期时间,具体看代码: function date2str(x,y) { var z ={y:x.getFullYear(),M:x.getMonth()+1 ...

  3. PHP程序输出日历

    以下代码只是简单实现日历的效果和逻辑思路,没有使用类封装,权当抛砖引玉,有兴趣的朋友可以封装起来,方便调用. <?php /** * PHP利用时间函数输出日历 * Rain.zen $ int ...

  4. Bootstrap3 代码-程序输出

    通过 <samp> 标签来标记程序输出的内容. This text is meant to be treated as sample output from a computer prog ...

  5. java笔记--重定向输出流实现程序输出到日志

    重定向输出流实现程序输出到日志 --如果朋友您想转载本文章请注明转载地址"http://www.cnblogs.com/XHJT/p/3877248.html "谢谢-- 利用Sy ...

  6. 双缓冲解决控制台应用程序输出“闪屏”(C/C++,Windows)

    使用 C 语言编写游戏的小伙伴们想必起初都要遇到这样的问题,在不断清屏输出数据的过程中,控制台中的输出内容会不断地闪屏.出现这个问题的原因是程序对数据处理花掉的时间影响到了数据显示,或许你可以使用局部 ...

  7. 用VSCode终端实现重定向比较程序输出和正确输出

    在刷 OJ 题目或者进行编程考试或比赛时,经常需要对编写好的程序进行测试,即运行编写好的程序,输入样例输入或者自己编写的输入数据,查看程序输出结果和样例输出或者正确输出是否一致.这种方法有很多弊端,当 ...

  8. cmake指定程序输出目录和库文件输出目录和拷贝文件

    概述 本文样式环境: win10+cmake 3.18 本文将介绍使用CMAKE配置项目输出目录和 LIbrary项目的输出目录 本文将介绍 cmake的file函数的基础用法之拷贝文件 重点, 这些 ...

  9. 【转】【译】JavaScript魔法揭秘--探索当前流行框架中部分功能的处理机制

    推荐语: 今天推荐一篇华为同事的同事翻译的一篇文章,推荐的主要原因是作为一个华为员工居然晚上还能写文章,由不得小钗不佩服!!! 其中的jQuery.angular.react皆是十分优秀的框架,各有特 ...

  10. javascript quine

    javascript有一些奇怪的性质,恩,比如说,非常容易写一个quine,即自己输出自己代码的东西. function a(){console.log(a.toString()+";a() ...

随机推荐

  1. apisix~hmac-auth插件的使用

    hmac-auth插件需要和 Consumer 一起使用,API 的使用者必须将密匙添加到请求头中以验证其请求,下面介绍它的主要用法 参数 algorithm 算法 默认hmac-sha256 [&q ...

  2. 使用Python解析求解拉普拉斯方程

    引言 大家好!今天我们将探讨一个经典的偏微分方程-拉普拉斯方程,并使用 Python 进行求解.拉普拉斯方程广泛应用于物理学中,尤其是在电磁学.流体力学和热传导等领域.通过这篇文章,你将了解什么是拉普 ...

  3. 使用SymPy求解矩阵微分方程

    引言 在数学.物理.工程等领域,微分方程常常被用来描述系统的变化和动态过程.对于多变量系统或者多方程系统,矩阵微分方程是非常常见的,它可以用来描述如电路.控制系统.振动系统等复杂的动态行为.今天,我们 ...

  4. 解决React Warning: Can't perform a React state update on an unmounted component. This is a no-op, but it indicates a memory leak in your application. To fix, ... useEffect cleanup function.

    在写react程序时遇到警告: Warning: Can't perform a React state update on an unmounted component. This is a no- ...

  5. access vba实现OLE对象保存到本地

    参考oletodisk的实现方法,更新为在64位office上野可以运行,函数模块代码如下: 1 Option Compare Database 2 Option Explicit 3 4 5 'DE ...

  6. Excel导入操作,poi

    导入操作,仅供参考,具体情况具体而论 @Override public ReturnObject inforImport(LogySbjsJdsbqxxxParts entity, HttpServl ...

  7. nim 语言使用 concept 实现 c# 的interface

    nim简介 nim语言兼顾C#等高级语言语义表达的丰富性,又有 C 语言的灵活性,以及超强的性能.下面是中文站对他的总结,我抄下来: Nim 是一种静态类型的.编译型.系统编程语言.它结合了其他成熟语 ...

  8. CTF实验吧:登陆一下? 不一样的SQL注入

    http://ctf5.shiyanbar.com/web/wonderkun/web/index.html 发现 过滤了很多SQL敏感字符,并且 转码绕过也并不行 发现'和=没有进行过滤 考虑万能密 ...

  9. 牛逼,这款开源聊天应用竟能一键召唤多个AI助手,跨平台通话神器!

    嗨,大家好,我是小华同学,关注我们获得"最新.最全.最优质"开源项目和高效工作学习方法 JiwuChat是一款基于Tauri2和Nuxt3构建的轻量化多平台即时通讯工具,仅约8MB ...

  10. Nacos源码—5.Nacos配置中心实现分析

    大纲 1.关于Nacos配置中心的几个问题 2.Nacos如何整合SpringBoot读取远程配置 3.Nacos加载读取远程配置数据的源码分析 4.客户端如何感知远程配置数据的变更 5.集群架构下节 ...