让我们分解一下ua.js
,看看发生了什么。洋葱的最外层是一个匿名函数:
var UA = (function (window, navigator)
{
/* anonymous function contents */
}(window, navigator));
所以 UA 被设置为这个匿名函数的返回值。那么匿名函数有什么作用呢?它设置了一个变量ua
。
var ua = (window.navigator && navigator.userAgent) || "";
它定义了一个函数,该函数detect
返回一个匿名函数,该函数针对 ua 测试 ua 的内容pattern
。
function detect(pattern) {
return function () {
return (pattern).test(ua);
};
}
请注意,调用detect(/something/)
不会返回 的值(/something/).test(ua)
。它只是返回一个将按需执行测试的闭包。
现在我们点击外部匿名函数的返回值,它看起来像这样(我已经删除了评论):
return { isChrome: detect(/webkit\W.*(chrome|chromium)\W/i),
isFirefox: detect(/mozilla.*\Wfirefox\W/i),
isGecko: detect(/mozilla(?!.*webkit).*\Wgecko\W/i),
...
whoami: function () {
return ua;
} }
这将返回一个Object
包含许多函数(isChrome
等)的实例,这些函数是调用创建的闭包detect()
。这意味着这些(pattern).test(ua)
检查的执行被推迟到有人实际调用UA.isChrome()
等等。
您可以想象另一种方法,其中所有测试都预先执行,并且 UA 成为包含一组标志的对象。这会产生(可能相当小)执行模式匹配的开销,而您作为开发人员并不感兴趣。