// 写法1:
var YAHOO = YAHOO || {};

// 写法2:
var YAHOO = window.YAHOO || {};

// 写法3:
if(typeof YAHOO === "undefined" || !YAHOO) {
    var YAHOO = {};
}

上面三种写法有什么区别?

写法1和写法2,都在全局作用域时,结果上并无区别。但如果在闭包里,写法1将不是预期结果:

var YAHOO = {};
// ...
(function(){
    var YAHOO = YAHOO || {};
    YAHOO.util = {};
})();
// ...
alert(YAHOO.util); // => undefined

原因很简单,闭包里,YAHOO 是局部变量。

写法2和写法3,在 99.99% 的应用场景下,结果上是等价的。但写法3更严谨,因为 JavaScript 的运行环境不一定是浏览器,因此全局变量并一定在挂载在 window 对象上。

写法3虽严谨,但也并非总是预期:

<script type="text/javascript">
    var YAHOO = 2;
</script>
<script type="text/javascript">
    if(typeof YAHOO === "undefined" || !YAHOO) {
        var YAHOO = {};
    }
    YAHOO.util = {};
    alert(YAHOO.util); // => undefined
</script>

上面一直提到一个概念:预期。我觉得这个预期可以描述为:

如果 YAHOO 已经定义成一个普通对象 {} 或函数对象 function, 则不要覆盖原来的定义。否则重新定义。

在这个预期的定义上,更严谨的一种写法是:

// 写法4:
if((typeof YAHOO !== "object" || window.YAHOO === null)
    && typeof YAHOO !== "function") {
    var YAHOO = {};
}

2009-09-02 更新:上面的写法增加 null 判断。

注:绝大部分情况下,写法2已经足够用。