问题 Javascript检查变量是否是窗口


你知道检查变量是否是javascript中的窗口对象的好方法吗? 我尝试过:

var variable=window;
Object.prototype.toString.call(variable);

在Firefox中它返回 "[object Window]" 但在IE中 "[object Object]" 所以这不是正确的方法。你知道一个准确的检查方法吗?


8581
2018-06-23 07:29


起源

你能不能做一个等价测试 window ? (somevar === window)?'yes':'no' - Stephen Ierodiaconou
但如果它是一个iframe窗口,它将无法工作。 - mck89
我很好奇,为什么你需要这样做? - Casey Chu
IE11返回[对象窗口] - jsnjack


答案:


是的,但我需要一种方法来检查每个窗口,而不仅仅是当前窗口

有几种方法可以做到这一点。最简单的方法是检查窗口对象上的一个或两个已知属性。还有 self 属性 - 对于每个窗口,你可以查看 self property等于window对象:

myvar.self == myvar;
window.self == window;
frameElement.contentWindow.self == frameElement.contentWindow;

12
2018-06-23 07:42



self 可以被覆盖,并且通常用作变量名来保留上下文。 - zzzzBov
@zzzzBov:那么,什么?大多数属性都可以被覆盖,但在尝试时很少会发生这种情况 “保留背景” 因为它不会发生在全局范围内,任何自尊的开发人员都会声明 var 其他地方。只要你参考 window.self 而不只是 self你应该没问题。如果它对任何人都很重要,我想他们可以使用 window.window 而不是 window.self,如果他们想要的话。它受到保护,不会被大多数现代浏览器覆盖。 - Andy E
@AndyE,我只是想找到一种更有弹性的方法来检查对象是否是一个 window 在学术意义上。例如, o = {}; o.self = o; isWindow(o) 将在您的版本中返回true。 jQuery 检查是否 setInterval 是的,所以 $.isWindow({setInterval:1})返回不正确。 - zzzzBov
@zzzzBov:我不相信有一个。 jQuery开发人员可能会选择 setInterval 因为它最不可能被重新用作另一个对象的属性名称,并且所有已知浏览器都支持它。一种现代的替代方案可能是使用 Object.prototype.toString(obj),将返回 [object global] 要么 [object Window] 在大多数浏览器中,主要的例外是IE 7及更低版本。但是,仍然没有完全弹性。也许在5年内。 - Andy E
@AndyE,我已经为这个问题添加了答案 认为 有弹性。它需要对边缘情况进行更多测试。 - zzzzBov


在AngularJS源代码中找到了这个。一个内衬和目标上的爆炸。

return variable && variable.document && variable.location && variable.alert && variable.setInterval;

3
2018-03-26 09:53



当变量未定义时,这将抛出异常(因为函数返回undefined而不是true / false):instanceof Window是最简单的检查方法。要使用此AngularJS代码,请将其包装在try {} catch或(typeof variable!=='undefined')中 - Raymond Naseef


怎么样:

isWindow = variable === window;

三等于防止类型强制,否则会使这更难做。


1
2018-06-23 07:32



是的,但我需要一种方法来检查每个窗口,而不仅仅是当前窗口。 - mck89
比较同一对象时,不需要进行类型严格检查。 - Andy E


在使用了许多选项后,我相信这是检测对象是否是跨浏览器窗口的最准确方法:

(function () {
    "use strict";
    var wStr;
    wStr = Object.prototype.toString.call(window);
    function isWindow(arg) {
        var e,
            str,
            self,
            hasSelf;
        //Safari returns DOMWindow
        //Chrome returns global
        //Firefox, Opera & IE9 return Window
        str = Object.prototype.toString.call(arg);
        switch (wStr) {
        case '[object DOMWindow]':
        case '[object Window]':
        case '[object global]':
            return str === wStr;
        }
        ///window objects always have a `self` property;
        ///however, `arg.self == arg` could be fooled by:
        ///var o = {};
        ///o.self = o;
        if ('self' in arg) {
            //`'self' in arg` is true if
            //the property exists on the object _or_ the prototype
            //`arg.hasOwnProperty('self')` is true only if
            //the property exists on the object
            hasSelf = arg.hasOwnProperty('self');
            try {
                if (hasSelf) {
                    self = arg.self;
                }
                delete arg.self;
                if (hasSelf) {
                    arg.self = self;
                }
            } catch (e) {
                //IE 7&8 throw an error when window.self is deleted
                return true;
            }
        }
        return false;
    }
}());

我需要进行更严格的单元测试,所以  让我知道出现的任何不一致之处。


1
2018-02-22 22:39



我已经更新了你的答案,因为有一个错误,然后我测试了它似乎工作,但我认为第一部分限制太多,因为几乎每个浏览器都有自己的方式将窗口转换为字符串,也许有超过3种变种。 - mck89
@ mck89,我主要关注的是5大:Firefox,Chrome,Safari,Opera和IE。如果浏览器规范化使用,那将是非常好的 '[object Window]'但是ECMAScript5规范 允许每个浏览器为其选择自己的值 [[Class]] 全局对象的属性。从这个意义上说,是的,这是一个相对限制性的实现,但我认为它比检查更有弹性 arg.self == arg,这很容易被愚弄。 - zzzzBov
我真的很赞赏你的努力,但我想知道谁需要这么严格。也许图书馆会利用它,但即使是jQuery也会这样想 if (obj && typeof obj === "object" && "setInterval" in obj) 足够了。什么时候需要有人写 o.self = o,以及有多少人有可能需要检查它是否是一个 window 目的?至于弹性,你的使用 "use strict" 使功能的弹性更低 arg.self === arg 因为a 类型错误 删除时将抛出 self 财产与 Configurable 属性设置为 false。 - Andy E
@AndyE,就像我之前的评论中提到的那样,我在学术意义上很好奇。我为自己设定了一个(大多数时候)万无一失的挑战 isWindow 功能。显然压倒一切 Object.prototype.toString, 要么 Function.prototype.call 会给出不正确的结果,但我理想地喜欢能够准确识别窗口对象的函数。 - zzzzBov
@zzzzBov:嗯,我当然可以理解。昨天当你对我的回答发表评论时,我快速浏览了一下 Object.prototype.toString 东西,注意到了 window.constructor.prototype.toString !== Object.prototype.toString 在所有主流浏览器中。我花了接下来的两个小时试图找出原因,但我仍然不知道答案。有些事情让你这样。 - Andy E


if(variable == window)

那当然只检查变量对象是否是这个窗口(即执行javascript的文档的窗口)。

或者,您可以尝试这样的事情:

if(variable.document && variable.location)

并检查是否存在一些窗口字段和/或函数 很确定 它是一个窗口......


0
2018-06-23 07:32





variable == window

有人仍然可以定义一个名为的局部变量 window。我不确定有什么办法可以适应所有这些恶作剧。有人可以创建一个复制大多数窗口属性和功能的对象,包括 toString


0
2018-06-23 07:31





var x = new Window();
x instanceof Window
var y = []
y instanceof Window

0
2018-03-26 11:09



用户知道的很少,但我们打开了一个窗口,他们不知道...... - redolent


以来 window 是全局变量,全局变量是全局对象的属性, window.window 会平等的 window。所以你可以测试:

if (mysteryVariable.window == mysteryVariable)
    ...

问题是,如果我们有这样的对象,这可能会被愚弄:

var q = {};
q.window = q;

如果那不太可能,那么您可以使用此代码。


-1
2018-06-23 07:51