Let’s get straight to the point.
Let’s look at jQuery’s $.isWindow function first:
function isWin(obj){
return obj && typeof obj === 'object' && 'setInterval' in obj;
}
The function itself It is very scientific, and it is mainly judged by checking whether the target object has the setInterval attribute.
However, the problem is that in the absence of a convention, it may not be reliable, such as:
var o={xx:'oo'};
o[' setInterval']=true;
console.log( isWin(o) ); // true
The above example adds the setInterval attribute to the object literal, and the fraud is successful.
But in fact Above, any non-null Object can be disguised in this way, such as an array:
var arr=[1,2,3];
arr['setInterval']=true;
console.log( isWin(arr) ); // true
Compared with the above property attribute checking, a more appropriate method is to use the toString function of the object to judge:
function isWin(obj){
return Object.prototype.toString.call(obj)==='[object Window]'
}
The above functions work well in standard browsers, but they also bring new compatibility issues:
// Result in ie6-8
Object.prototype.toString.call(window)==='[ object Window]'; // false
Object.prototype.toString.call(window)==='[object Object]'; // true
// chrome
Object.prototype.toString.call (window)==='[object global]'; // true
// safari
Object.prototype.toString.call(window)==='[object DOMWindow]'; // true
Sure enough, the main problem comes from the evil IEs. Fortunately, there is always a path, which reminds me of a supernatural event in IE:
// The following two lines, believe it or not?
console.log( window= =document ); // true
console.log( document==window ); // false
Writing this, I think the final solution has come out:
function isWin(obj){
return/Window| global/.test({}.toString.call(obj))||obj==obj.document&&obj.document!=obj;
}