我能否在JavaScript中向“window”对象添加属性?

63

我能在 JavaScript 中为 'window' 对象添加任何随机属性吗?就像这样:

window.my_own_attr = "my_value"

它是否与任何库存在副作用?并且它是否跨浏览器兼容?

7个回答

85
在JavaScript中,我可以给'window'对象添加任何随机属性吗?
是的,就像你展示的那样。
那么它会对任何库产生副作用吗?
不会,除非您使用一个设置了一个您随后覆盖的属性的库。
它在跨浏览器兼容吗?
完全兼容。
话虽如此,这种做法通常是不被赞成的。您可能会意外地覆盖掉一些您不希望的东西。

1
参考此链接:https://dev59.com/MnRA5IYBdhLWcg3wsgBP,我不想更改“window.name”,因此将使用一些独特的奇怪名称来代表我的应用程序。 - akkishore
1
好的,看起来只有 'window.name' 在重新加载后保留了。 :( - akkishore
15
回答OP的三个问题并提供信息性回答,这个回答得到了+1的点赞。 - David 'the bald ginger'

17
在所有浏览器中,window 是 JavaScript 的全局命名空间。每个属性或方法都存在于该命名空间中。因此,如果您将一个属性分配给window,它实际上就是一个全局变量。
示例:

window.myConstant = 5;

// note: a var declaration will be a window property too
// note 2: 'let' or 'const' will not be window properties
// below can also be done without 'var'.
var myConstantGlobal = 4;

console.log(`multiply(10) => ${multiply(10)}`);
console.log(`multiply() => ${multiply()}`);
console.log(`multiplyGlobalVar(10)) => ${multiplyGlobalVar(10)}`);
console.log(`multiplyGlobalVar() => ${multiplyGlobalVar()}`);
    
function multiply(val){
  return myConstant * (val || 1);
}

function multiplyGlobalVar(val){
  return window.myConstantGlobal * (val || 1);
}

在使用JavaScript框架时要非常小心。例如,如果您声明了window.JQuery并使用JQuery框架,则JQuery命名空间将被您的赋值所替换,从而使其无用。


5

是的,你可以这样做,但一般情况下不应该这么做。

window 对象也是 JS 默认的“全局”对象,因此所有全局变量都会被添加到其中。

除非你覆盖了已经存在的属性,否则不太可能破坏任何东西,但是将变量放在 window 上或者创建很多全局变量被认为是不好的做法。


2
如果您创建一个具有许多属性的对象,则混乱将是可管理的。 - theking2

5
我不会重复其他人所说的关于此做法的hackyness。但在使用类似Angular这样的刚性框架与vanilla HTML / JS(或jQuery)代码混合时,它可能非常有用。这也是hacky且不被赞同的,但有时有很好的理由,例如如果您有许多现有的JS代码将挑战集成到框架中。
对我来说更有趣的问题是如何利用向全局window对象添加属性的能力。当我想将Angular provider(service)的方法暴露给无法注入该服务的代码时(可能因为它运行在Angular DI框架之外),我使用的模式如下:
1.在您的顶层模块中将服务定义为provider。 2.在app.component.js(或任何导入提供程序的顶级组件)的构造函数或onInit中正常注入提供程序,执行任何需要的一次性初始化,然后调用window ['MyServiceName'] = this
假设您已经设计了provider以遵循Singleton模式,那么您的provider方法现在可以安全地从任何地方进行调用。非Angular脚本只需调用window ['MyServiceName'].methodName()即可。

0

正如其他人指出的那样,是的,你可以这样做,这意味着添加“全局变量”。

拥有全局变量并不是最佳实践,但有时它是最简单的方法。例如,如果您使用IFrames并希望子窗口访问父窗口的某个属性,则此属性必须是“全局”的才能被子窗口访问。但这也表明它并不是“真正的全局”,它只是特定窗口的属性。但它可能会与其他属性名称冲突,例如在同一窗口中定义的函数名称,也许是您使用的某些库。

所以我们知道全局变量是不好的。如果我们决定仍然使用它们,有没有什么方法可以将它们的坏处最小化?

是的,有:定义一个具有更或多或少独特名称的SINGLE全局变量,并将一个OBJECT存储到其中。将您需要的所有其他“变量”作为该单个对象的字段存储。

这样,您不需要添加超过一个单个全局变量(每个窗口)。不太糟糕。

将其命名为更或多或少独特,以便不太可能与任何其他单个全局变量发生冲突。例如,您可以使用您的名称+“s”作为变量名:

window.Panus  = {}; 

:-)


1
在ES6中,您可以进一步定义一个全局变量为const。然后,如果有人尝试覆盖它,您应该会收到一个错误消息,告诉您发生了什么。 - Panu Logic

0

这样做没问题,除非使用相同的变量名称与任何库冲突,它可以在所有浏览器中工作,但不建议这样做,因为这会创建全局JS变量。


“window” 是一个全局对象。所以这样应该没问题吧? - akkishore
在您的情况下,您可以直接访问 my_own_attr 而不需要使用 window.,这会使其成为全局变量并可能与其他同名变量发生冲突。 - Riz

0

在IE中,如果一个元素有一个id,则该节点可以作为属性在window对象上访问:

<div id="num"></div>

alert(num); //Element

num = 3; //抛出异常

var num = 3; //ok


仅澄清一下,这条评论针对的是 IE6 〜 IE9(它们在 2012 年很流行),并且对于较新版本的 IE(Edge)已不再适用。 - Kernel James

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接