用匿名函数避免命名冲突

本文解析了Google loader中使用匿名函数的原因及好处,探讨了如何通过匿名函数避免命名冲突并实现良好的封装。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >


本文是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表的启发。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值