写一个打印自身源代码的 JS 程序 - JS 的 Quine 程序实现

简介: Quine 程序是指一个能够输出自身代码的计算机程序。本文讲解了两种在JS中实现Quine程序的方法,这两种方法分别利用了函数到字符串的转换和格式化字符串。

Quine 程序是指一个能够输出自身代码的计算机程序。Quine 程序的实现是计算机科学中一个有趣的问题,不同语言中有不同的实现方式,常见的技巧包括代码注入、字符串插值或反射等。在 JavaScript 中我们有多种方法来实现 Quine 程序,本文将讲解其中的两种常见方法。

1. 函数转字符串

第一种思路是利用函数转化为字符串时会输出自身源代码的特性,我们可以通过打印出函数转化为字符串的结果来获取函数的源代码。

function f() {
    console.log(f.toString()) }
f()
// 结果:function f() { console.log(f.toString()) }

这段代码中我们声明了一个函数f,它所做的事情就是把自己转化为字符串,然后打印出来。调用这个函数我们就可以在控制台看到它的源代码内容。但是我们的目的是打印整个程序的源代码,这里第二行的函数调用语句没有被打印出来。我们只要在函数里面把这个函数调用语句也打印出来就好。

function f() {
    console.log(f.toString(), '\nf()') }
f()
// 运行结果:
// function f() { console.log(f.toString(), '\nf()') } 
// f()

这里我们利用了console.log会把所有的参数按顺序打印的特性。但这种写法还不够简洁,因为这个函数我们只调用了一次,所以完全可以写成立即执行函数(IIFE)的形式。同时我们还使用了模版字符串来简化字符串的拼接,注意这里不再需要显式地调用toString,因为模版字符串在解析的时候会自动帮我们调用。同时要记得在打印的时候把包裹函数的括号和调用函数的括号也打印出来。

(function f() {
    console.log(`(${
     f})()`) })()
// 运行结果:
// (function f() { console.log(`(${f})()`) })()

除了使用常规的命名函数声明的方式,我们也可以用箭头函数来实现程序自打印。

(f = () => console.log(`(f = ${
     f})()`))()

这段代码做的事情和刚才的程序类似,我们声明了一个变量f(因为没有添加变量声明关键字,所以相当于声明了一个全局变量),这个变量指向一个箭头函数,它所做的事情就是打印自己的源代码,并在周围把 IIFE(立即执行函数)和变量声明的代码也打印出来。这样就可以实现整个程序源代码的打印了。

如果把这个例子的变量名和格式稍微调整一下,可以得到这样一行代码

({
   mathJaxContainer[0]}={
   mathJaxContainer[1]}})()`))()

这行代码看起来没有任何意义,更像是一个颜文字或者一堆乱码,但它实际上做的事情跟刚刚的代码一样。只是把变量名从f换成了$,并且把箭头函数的参数列表从()换成了_(两者都是表示没有任何参数的意思)。

2. 格式化字符串

格式化字符串是 Quine 程序最常见的实现方式,因为大部分的语言都支持格式化字符串。JS同样可以在console.log中使用格式化字符串,其规则和C语言基本一致。这里我们先简单讲解一下其使用方法:

console.log('%s-%d', 'hello', 1); // 输出:hello-1

这段代码中的第一个参数'%s %d'是一个格式化字符串,其中 %s%d 是占位符,分别表示字符串类型和数字类型。后面的参数 'hello' 和 1.0 是用于填充格式化字符串的值。执行这段代码会将字符串中的%s替换为hello%d替换为1,最终输出hello-1。需要注意的是,占位符的数量和类型必须与后面的参数数量和类型相匹配,否则会导致运行时错误。

利用格式化字符串我们可以轻松地实现 Quine 程序。其根本思想和第一种方法类似,都是利用变量可以打印自身的特性。具体的实现方法如下所示:

const s = "const s = '%s'; console.log(s, s);"; console.log(s, s);
// 输出:const s = 'const s = '%s'; console.log(s, s);'; console.log(s, s);

在这段代码中我们把s设置为一个格式化字符串,留一个字符串的占位符,在console.log语句中用s自身的内容替换占位符。在占位符的周围把变量声明语句和console.log语句的代码写上就OK了。

总结

有两种方法可以实现JS的 Quine 程序:

  1. 第一种方法具有鲜明的 JavaScript 特色,利用函数转化为字符串是自身源代码的特性来打印整个程序的源代码。
  2. 第二种方法更为常见,在绝大多数的语言中都可以用这种方法实现程序自打印,即通过利用格式化字符串来让变量打印自身。

本文作者:wzkMaster,如果有帮助的话欢迎点赞收藏~

相关文章
|
3月前
|
JavaScript Java Serverless
函数计算产品使用问题之如何使用Node.js编写程序
函数计算产品作为一种事件驱动的全托管计算服务,让用户能够专注于业务逻辑的编写,而无需关心底层服务器的管理与运维。你可以有效地利用函数计算产品来支撑各类应用场景,从简单的数据处理到复杂的业务逻辑,实现快速、高效、低成本的云上部署与运维。以下是一些关于使用函数计算产品的合集和要点,帮助你更好地理解和应用这一服务。
|
11天前
|
JavaScript 前端开发
利用事件循环提高 JavaScript 程序的性能
本文介绍了事件循环在JavaScript中的工作原理,以及如何通过合理利用事件循环来优化程序性能,包括异步操作、任务优先级和避免阻塞等技巧。
|
1月前
|
JavaScript 前端开发
如何使用Vue.js构建响应式Web应用程序
【10月更文挑战第9天】如何使用Vue.js构建响应式Web应用程序
|
3月前
|
JavaScript 前端开发
JavaScript 源代码大放送
JavaScript 不仅是前端开发的首选语言,通过 NodeJS 还能用于开发高性能后端服务,甚至在硬件编程中也崭露头角,正逐步成为全能型语言。此段代码提供了一个自定义日期格式验证的实用函数 `isValidDate`,简化了日期有效性检查,无需依赖庞大的第三方库。此外,还提供了获取元素最大尺寸和高亮文本的函数,以及一个为文字添加动画效果的 jQuery 插件,适用于多种开发场景。
19 2
|
4月前
|
JavaScript 前端开发 程序员
《JavaScript权威指南第7版》中文PDF+英文PDF+源代码 +JavaScript权威指南(第6版)(附源码)PDF下载阅读分享推荐
JavaScript是Web标准语言,广泛应用于各类浏览器,造就了其最广泛部署的地位。Node.js的兴起扩展了JavaScript的使用场景,使其成为开发者首选语言。无论新手还是经验丰富的程序员,都能受益于学习JavaScript。[《JavaScript权威指南第7版》资源链接](https://zhangfeidezhu.com/?p=224)
271 5
《JavaScript权威指南第7版》中文PDF+英文PDF+源代码 +JavaScript权威指南(第6版)(附源码)PDF下载阅读分享推荐
|
3月前
|
JavaScript 前端开发
必备的 JavaScript 源代码大放送
必备的 JavaScript 源代码大放送
18 1
|
4月前
|
关系型数据库 MySQL 存储
|
4月前
|
前端开发 JavaScript
文本,wangEditor5展示HTML无样式,wangEditor5如何看源码,Ctrl + U看CSS文件,代码高亮,Prism.js可以实现,解决方法,参考网页源代码的写法
文本,wangEditor5展示HTML无样式,wangEditor5如何看源码,Ctrl + U看CSS文件,代码高亮,Prism.js可以实现,解决方法,参考网页源代码的写法
|
5月前
|
Web App开发 JavaScript 前端开发
程序员必知:【three.js练习程序】创建地球贴图
程序员必知:【three.js练习程序】创建地球贴图
49 0
|
5月前
|
JavaScript
Vue.js中使用.self修饰符来限制事件处理程序的作用域
Vue.js中使用.self修饰符来限制事件处理程序的作用域