jQuery源码isWindow方法实现逻辑疑问及替代方案可行性问询
先看一下jQuery中isWindow方法的原始实现:
isWindow: function( obj ) { return obj != null && obj === obj.window; }
咱们来逐个拆解里面的细节:
1. 为什么要先判断obj != null?
这个判断其实是做安全防护。你想啊,如果传入的obj是null或者undefined,直接去访问obj.window会立刻抛出TypeError(因为null/undefined没有任何属性)。加上obj != null之后,就能提前把这两种无效输入过滤掉,避免代码报错,同时直接返回false——毕竟null和undefined肯定不是window对象,符合预期。
举个反例,如果去掉这个判断:
isWindow: function( obj ) { return obj === obj.window; }
当你调用$.isWindow(null)时,浏览器会直接报错:Cannot read properties of null (reading 'window'),这显然不是我们想要的结果。
2. 为什么用obj === obj.window而不是obj === window?
这是为了支持多窗口/iframe场景。
在浏览器环境中,每个独立的窗口(比如新打开的标签页)或者iframe,都有自己独立的window对象,而且每个window对象的window属性都会指向它自己(比如iframe里的window.window就是iframe自身的window)。
如果用obj === window,那只能判断传入的对象是不是当前页面的window对象,但如果是iframe里的window,或者其他标签页的window,这个判断就会返回false,但实际上它们也是window对象。
而obj === obj.window这个判断,不管是当前页面的window,还是iframe里的window,只要是一个标准的window对象,它的window属性必然指向自身,所以这个判断能准确识别所有合法的window对象,兼容性更强。
3. 能不能改写成isWindow:function(obj){ return obj===window; }?
绝对不行!这个改写会在多窗口/iframe场景下失效,咱们用实际测试用例来说明:
测试用例1:当前页面的window
console.log($.isWindow(window)) // true console.log(window === window) // true
这个场景下两者结果一致,没问题。
测试用例2:null和undefined
console.log($.isWindow(null)) // false console.log(null === window) // false console.log($.isWindow(undefined)) // false console.log(undefined === window) // false
这个场景下结果也一致。
测试用例3:iframe中的window对象
<!-- 页面中插入一个iframe --> <iframe id="testFrame" srcdoc="<body></body>"></iframe> <script> // 等待iframe加载完成 document.getElementById('testFrame').onload = function() { const iframeWin = this.contentWindow; // 用jQuery原方法判断 console.log('原方法判断iframe window:', $.isWindow(iframeWin)); // 输出true // 用改写后的方法判断 console.log('改写方法判断iframe window:', iframeWin === window); // 输出false }; </script>
看到没?iframe里的window明明是一个合法的window对象,但改写后的方法会错误地返回false,而原方法能正确识别。这就是为什么不能直接用obj === window的核心原因。
内容的提问来源于stack exchange,提问作者兰为鹏

