【挑战极限】最短的javascript: 地址栏载入脚本

标签: 挑战 极限 javascript | 发表时间:2011-10-08 19:29 | 作者:EtherDream mingelz
出处:http://www.cnblogs.com/index-html/

  相信大家都在地址栏里用javascript:的形式执行过脚本。这种方法简单实用,测试比较短的脚本时经常用到。并且可以添加到收藏夹里,随时点击调用。

 

  不过脚本比较长的时候,需要复制密密麻麻一大段到地址栏里,显得很不美观,而且脚本修改起来也很不容易。因此一般先把脚本写在单独一个文件里,然后用javascript: 的形式动态载入脚本到页面中。不少网页插件都是用这个方法载入。

 

  平时,我们用最简单的代码实现动态载入:

javascript:var o=document.createElement('script');o.src='...';document.body.appendChild(o);void(0)

  当然,这对于载入插件来说足够OK了。但是不久前看到一个稍有修改的方法,让我开始琢磨这段代码究竟可以压缩到多短!

 

  他的代码大致相同,只是更严谨: 

javascript:(function(o){o.src='...';document.body.appendChild(o)})(document.createElement('script'));void(0)

  虽然代码比先前的还长,但是将变量置于闭包中,避免潜在的冲突。并且将  document.createElement作为闭包的参数,巧妙的节省了一个var单词。

  闲来无事,于是考虑起这代码能否精简再精简。顺便复习下js里面的各种特性。

  

  当然,首先默认了几个地址栏载入脚本要遵循的规则:

  1. 不引入全局变量

  2. 兼容主流浏览器

  3. 载入过程不影响页面 

  

  > 不影响全局变量,我们需要使用闭包来隐藏我们的私有变量;

  > 兼容主流浏览器,就必须使用标准的方法,兼容性判断只会增加代码长度;

  > 如果简单的使用innerHTML添加元素,就有可能导致存在的元素刷新;

  

  于是我们开始逐步分析。

  显然,最先想到的就是匿名闭包的调用。

  通常我们都是用:  (function(){})()  的形式调用一个匿名闭包。注意红色的优先级括号是必不可缺的,否则就是一个错误的语法。

  但也可以使用另一种形式:+function(){}() 前面的+号可以换成-!~等等一元操作符。不过这仅仅是1字节之差。

 

  另一个显然的,就是可以把void(0)的参数替换成闭包调用的表达式。void虽然只是个关键字,但有类似函数的功能,对于任何参数都返回undefined。如果没有void,在地址栏执行了javascript:后,页面就变成了脚本表达式返回值,大家应该都见过。

   

  于是经过显而易见的观察,略微减少了3个字符。

javascript:void(+function(o){o.src='...';document.body.appendChild(o)}(document.createElement('script')))

  

  不过上面都是浅层次的观察。现在我们来仔细的分析。

   

  我们为什么要使用闭包,就是为了防止我们的变量和页面里的冲突。那么可以不使用变量吗?想要不出现变量,唯一办法就是使用链式的连等操作:利用上个操作的返回值作为下个操作的参数。这段代码共有3个操作:创建脚本元素/脚本元素src赋值/添加脚本元素。仔细参考下W3C的手册,DOM.appendChild不仅可以添加元素,并且返回值也是此元素。而src赋值和元素添加的顺序可以互换。因此我们可以用链式操作,从而彻底告别闭包和变量:

javascript:void(document.body.appendChild(document.createElement('script')).src='...')

  这一步,我们精简了19个字符!
  

  我们继续观察。上面的代码里出现了2个document。我们如果用一个短变量代替的话又可以减少字数。但使用了变量的话又会出现冲突的问题,于是又要用到闭包。。。仔细的回忆下,js里有个我们平时不推荐使用的东西:with。没错,使用他就可以解决这个问题。我是只需with(document){...}即可。因为只有一行代码,所以那对大括号也可以去掉。于是又减少了4个字符:

javascript:with(document)void(body.appendChild(createElement('script')).src='...')

  值得注意的是,void不再套在最外层了,因为with和if, for他们一样,不再是表达式,而是语句了。

  

  此时,代码里的每句都是各司其责,连重复的单词都找不到了。我们还能否再精简?如果硬要找,那也只得从void这家伙身上找了。如果去掉它,那地址栏执行后,页面就变成了脚本元素的src字符了。显然删不得。但我们可以尝试换个,比如alert。在对话框过后,页面仍保留着。

  先前说了,void的功能仅仅是返回一个undefined,而alert没有返回值。这里就不得不说javascript与其他语言的不同之处了。在其他的语言里,几乎都有函数/过程这么两概念,过程就是没有返回值的函数。不过js可不同,在js里任何函数都有一个返回值,即使“ 没有返回值 ”也是一种返回值,他就是undefined。所以alert和void有着相同的返回值:undefined。只要地址栏执行后结果是它,页面就不会转跳,而其他诸如false,0,null,NaN等等都不行。

  

  于是我们只需让表达式返回的是undefined就可以了,但必须比void()这几个字符短。要产生一个undefined,除了它字面常量外,另外就是调用没有返回值的函数,或者访问一个对象不存在的属性。我们要尽可能简短。如果页面里使用了jQuery的话,我们用$.X就可以得到一个undefined。但没用jq的话,就不能保证是否存在变量$了。既然找不到足够简短的全局变量,我们可以用json创造个匿名的,比如[]或{},然后访问他的不存在属性,比如[].X。于是,我们可以告别void了:

javascript:with(document)body.appendChild(createElement('script')).src='...';[].X

  
  这样就减少了1个字节。我们还可以合并下代码,用表达式替换X:

javascript:with(document)[][body.appendChild(createElement('script')).src='...']

  这样又减少了1个字节。
  

  事实上,js里的任何一个变量都是继承于Object的,即使数字也不例外。所以,我们完全可以用一个数字替换[],这样更进一步减少1个字符:

javascript:with(document)0[body.appendChild(createElement('script')).src='...']

  到此,代码里除了src字符外,缩短到76字节。

  

  当然,最终的极限仍在探索中。。。

   

  配合Google的短域名服务Google URL Shortener,我们可以缩短脚本的URL,例如:

javascript:with(document)0[body.appendChild(createElement('script')).src='http://goo.gl/QPp29']

作者: EtherDream 发表于 2011-10-08 19:29 原文链接

评论: 15 查看评论 发表评论


最新新闻:
· 电影也App化,MoPix助电影制作者将电影转化成应用出售(2011-10-13 21:32)
· 窝窝回应规模撤站:取消分站服务团队 服务照常(2011-10-13 21:28)
· iOS 5评测(2011-10-13 21:26)
· 华尔街日报引发争论:为什么创业公司难筹钱?(2011-10-13 21:19)
· 谷歌十大高薪职位:首席软件工程师居首(2011-10-13 21:15)

编辑推荐:最老程序员创业札记:全文检索、数据挖掘、推荐引擎应用45

网站导航:博客园首页  我的园子  新闻  闪存  小组  博问  知识库

相关 [挑战 极限 javascript] 推荐:

【挑战极限】最短的javascript: 地址栏载入脚本

- mingelz - 博客园-EtherDream の 原创空间
  相信大家都在地址栏里用javascript:的形式执行过脚本. 这种方法简单实用,测试比较短的脚本时经常用到. 并且可以添加到收藏夹里,随时点击调用.   不过脚本比较长的时候,需要复制密密麻麻一大段到地址栏里,显得很不美观,而且脚本修改起来也很不容易. 因此一般先把脚本写在单独一个文件里,然后用javascript: 的形式动态载入脚本到页面中.

五大悖论,挑战智商极限

- - 左岸读书_blog
NO.1——说谎者悖论(1iar paradox or Epimenides’ paradox). 公元前6世纪古希腊哲学家伊壁孟德所创的四个悖论之一. 具体为:他说:“所有的克里特人都是撒谎者”. 如果他说的是实话,那么克里特人都是撒谎者,而伊壁孟德是克里特人,他必然说了假话. 如果他确实撒了谎,那么克里特人就都不是说谎的人,因而伊壁孟德也必然说了真话.

【挑战极限】最短AJAX创建代码

- We_Get - 博客园-首页原创精华区
  下午写了篇最短地址栏载入脚本的文章. 不过再怎么短仍然没什么意思,纯属娱乐下罢了. 刚才想起能缩短个平时经常用到的代码就好了,于是现在一边写一边来研究,最短的XMLHTTP组建创建.   假如你的脚本只针对某个浏览器开发,那么创建XMLHTTP是很简单的一件事,用XMLHttpRequest或者ActiveXObject即可.

tomcat7.0性能优化-挑战极限完整版

- - 企业架构 - ITeye博客
1.1 tomcat运行模式. 1.2 APR与tomcat-native安装. 到http://apr.apache.org/下载下面3个包. 2.安装apr-iconv. 4安装tomcat-native. 在tomcat目录下,找到bin/tomcat-native-1.1.24-src. 官方参考文档 http://tomcat.apache.org/tomcat-7.0-doc/config/http.html.

谷奥: Google 内部头脑风暴出来的广告赚钱计划,挑战人类隐私极限

- rudan - 谷奥聚合——谷奥主站+谷安 aggregator
华尔街日报拿到了一份号称是Google内部备忘录的文件,该文件描述了公司未来的赚钱渠道展望,其中主要描绘的赚钱渠道主要集中在用户隐私数据交换和广告方面,其中一些想法几乎在挑战人类隐私极限,比如:. Get Paid:用户可以选择加入这个Get Paid项目,通过分享他们所有用户数据来得到ISP宽带服务商的优惠价格或是某种形式的返点.

最近好多自杀的官员啊!!这年头没点身份地位身怀绝技挑战极限的绝技还真没好意思自杀

- 牛 - 天朝娱乐 | 每天开心一下!
感谢 天朝临时工 投递给天朝娱乐. 【襄阳市襄州区审计局官员检查帐单后被人扔下楼】2011年8月26日晚18:00-19:00左右,襄阳市襄州区有一个官员叫曹新权(任职当地站长、会计)在审计局查账的过程中残忍被人杀害,死者被挑了脚筋,又把人从四楼窗口扔下,死者的尸体都还没检验,就被警方初步结论为:跳楼自杀.

Javascript诞生记

- Milido - 阮一峰的网络日志
二周前,我谈了一点Javascript的历史. 今天把这部分补全,从历史的角度,说明Javascript到底是如何设计出来的. 只有了解这段历史,才能明白Javascript为什么是现在的样子. 我依据的资料,主要是Brendan Eich的自述. "1994年,网景公司(Netscape)发布了Navigator浏览器0.9版.

JavaScript,你懂的

- dylan - keakon的涂鸦馆
经常有人问我,JavaScript应该怎么学. 先学基本语法,如果曾学过C等语言,应该1小时内就能掌握了. 再去使用内置的函数、方法和DOM API,熟悉它能干什么;而在学习DOM API的过程中,你还不得不与HTML和CSS打交道. 然后弄懂匿名函数和闭包,学会至少一个常用的JavaScript库(例如jQuery).

Javascript 里跑Linux

- rockmaple - Shellex's Blog
牛逼到暴的大拿 Fabrice Bellard,用Javascript实现了一个x86 PC 模拟器,然后成功在这个模拟器里面跑Linux(请用Firefox 4 / Google Chrome 11打开,Chome 12有BUG). 关于这个东西… 伊说 “I did it for fun“,大大啊大大啊….

高效 JavaScript

- xtps - ITeye论坛最新讨论
传统上,网页中不会有大量的脚本,至少脚本很少会影响网页的性能. 但随着网页越来越像 Web 应用程序,脚本的效率对网页性能影响越来越大. 而且使用 Web 技术开发的应用程序现在越来越多,因此提高脚本的性能变得很重要. 对于桌面应用程序,通常使用编译器将源代码转换为二进制程序. 编译器可以花费大量时间优化最终二进制程序的效率.