用匿名函数避免命名冲突

本文是google.loader 代码欣赏系列的第二部分。

第一个匪夷所思的地方,可能就是这一段了

if (!google.loader) {
google.loader = {};
google.loader.ServiceBase = “http://www.google.com/uds”;
google.loader.ApiKey = “internal”;
google.loader.KeyVerified = true;
google.loader.LoadFailure = false;
google.loader.AdditionalParams = “”;
(function() {
//大量的函数定义,变量声明以及函数的执行(整整100多行)
})()
}

基本上就是说,它写了一个这样的语法:

(function(){})()

就算是看得懂,这么绕来绕去,除了炫耀之外,又有意义呢?

匿名函数

先撇开Google的代码,看一下JavaScript其实是支持这种形式的行数定义的:

function(msg){ alert(msg); }(“hello world”);

这其实是两步:第一步,定义了一个函数,相当于:

var abc = function(msg) { alert(msg);}

第二步,立刻执行它:

abc(“hello world”);

把两个语句拼接在一起,然后去掉abc这个函数的名字,就成了现在的语法形式。

结合前面的

google.loader = {};

一起看,其实在这里是定义了google.loader这个对象的一个匿名的成员函数,并且立刻执行了这个成员函数(就是说完成里面的一些列初始化的时候需要干的事情)。

匿名函数的用处

虽然可以理解这里是个匿名函数,但是为什么要这么做呢?

我猜想(请注意,所有这里想的都是一个猜想,并且可能是众多原因之中的一种而已,欢迎大家补充),最主要的考虑是避免命名冲突。

因为这段JavaScript作为Google的其他的各项服务的入口,是会被全球很多的网页引用的。像任何的JavaScript引用(包括PHP的引用),如果被引用的代码和外面的代码一不小心用了同样的名字,就不可避免的发生命名冲突。对于小范围的代码或许还可以用起很怪异的名字的方法企图避免,而对于Google这样的应用,靠运气就有些说不过去。如果是一个匿名函数,外面将永远无法直接访问它(总不能写一个这样的一个没有函数名的调用吧:())。从这一点来说,不可能有命名冲突。

封装

另外的一个好处,有可能是为了更好的封装。比如在这个函数里面,有很多的函数定义,比如

q(); p(); m(); g(); i()

还有大量的变量:

var j; var h; var l;

等等。在JavaScript里面没有简单的private这样的定义私有函数或者私有函数的方法。如果调用者可以随心所欲的访问到这些中间的(随时可能变化,甚至移除)成员。对于这么一个开肠破肚,一览无余的对象,从一个API提供者的角度来看(和使用者的角度来看),的确是个挺恐怖的事情。

如果放在一个匿名的函数里面,外界就再也没有办法直接访问到里面的函数了。内部的逻辑被完美的封装了起来。这样一来,这些函数和变量多么的安全!

安全是安全了,但是定义了这么多的函数,仅仅是为了不被外界访问吗?显然不是,所以接下来要做的事情,就是把这些函数输出出去,也就是google_exportSymbol,或者说是函数g()要做的事情。

且听下回分解。

注:接下来,或许还要说说: 输出函数供开发者使用, JavaScript中的面向对象, prototype的扩展方式, Undocumented的神秘参数, 编译后的JavaSscript好比汇编语言,和 Symbol表的启发。

《用匿名函数避免命名冲突》上的12个想法

  1. (function(){})()为最常用的限定变量作用域的方法…
    干净的全局空间是很多jslib现在所倡导的..

    javascript的变量作用域是function,而不是其他的类c语言的block.

  2. (function(){})()的目的是变量私有化.
    命名空间现在的做法一般是下面这样做.
    var com = {};
    com.google = {};
    com.google.reader = {
    };
    当然将上面的过程可以做个封装函数.

  3. function g(c,a){
    var b=c.split(/\./);
    var d=window;
    for(var e=0;e d=d[b[e]]
    }
    d[b[b.length-1]]=a
    }
    这个方法就是上面描述的封装函数,嘿嘿.

  4. 恩,看到这一篇了。
    哈哈,偶经历过AS1的Coder来看,确实感觉非常亲切!!!
    感谢jianshuo老师带来的精彩分析~~

  5. 匿名函数在访问域的控制上用处比较大,如果用JS做平台,现在的YUI这个开源项目做的不错,不论是社区还是代码文档,而且Yahoo的首页也是基于YUI来做,直接和GWT竞争的。感觉YUI更出色一些。

  6. 其实 javascript这样的应用总是觉得象看你前一片文章别人说过的一样,好像是经过程序优化压缩过的?

    不过即使是这样,分析出这么多东西也是受教了。

    javascript 我觉得最大的特点需要我们考虑的就是让它 人尽其用,而不是乱用。 比如我最近接手的一个项目就是改善一个网站的环境。

    http://www.babyone.com.cn/

    在我接手前,首页就一个js 加载 flash 的脚本。 根本对内页没有任何链接。

    一通修改,现在看起来似乎满意了一点,有兴趣的可以打开察看源代码来了解我改了些什么哈。

  7. 一通修改,babyone这个网站还是一看就知道没什么前途……那改了是要干吗呢……

发表评论

邮箱地址不会被公开。 必填项已用*标注