在Windows对象上设置属性是否被认为是糟糕的做法?

21

我正在编写一个相当复杂的JavaScript应用程序,它具有MVC架构。我使用Prototype的 Class 支持和模块化模式实现了这个架构。该应用程序使用 AJAX 和观察者模式。当DOM加载完成时,我创建控制器实例,将视图以及从JSON数据创建的一些模型传递给它,然后它开始工作。

然而,我发现我必须将我的控制器实例设置为 Window 对象的属性,即不使用 var 声明,因为我有一个AJAX成功回调函数,它会刷新控制器所拥有的视图对象,在代码的这一点上,我的MVC世界已经不在范围内了。

我尝试将视图对象作为参数传递到包含AJAX代码的函数中,但这变得非常混乱,并导致了一些可怕的MVC模式违规,例如耦合模型和视图,这样做很糟糕。

像直接在 Window 上存储我的控制器实例这样的做法是否被认为是不好的形式呢?这有点像使用全局变量,但我看不出其他方法。


你能发一小段代码示例吗? - Ryan Doherty
恐怕我不能这样做。我现在在家,代码在工作中,更重要的是,我认为我需要发布大量的代码来说明问题 - 我不喜欢阅读“墙壁式”的问题,所以我也不想让别人遭受同样的痛苦! - John Topley
1
MVC为什么会超出范围?你的AJAX回调函数至少应该捕获对它的引用,不是吗? - MooGoo
我对闭包不太熟悉。实质上,AJAX函数在控制器内部,由一个模型函数调用,该模型函数本身又是由另一个模型实例更新而调用的(因此观察者模式)。我正在使用Prototype的'onSuccess'回调,并且在那一点上'this'指的是'Window'。 - John Topley
1
然后只需在回调代码之前放置类似于 var that = this 的内容,然后将回调中所有对 this 的引用更改为 that。或者,使用 Prototype 的 Function.bind 来修复 this 的值。 - MooGoo
3个回答

14
在窗口对象上设置属性相当于创建全局变量。也就是说,有时不可避免地需要这样做,但应尽可能将其保持在最低限度,因为它最终会污染全局命名空间。
在您的情况下,创建单个属性并不那么糟糕。如果您想特别小心,可以明确地为需要全局访问的任何内容创建命名空间:
// In init:
var mynamespace = {};

. . .

// Once the controller is available:
var namespace = window.mynamespace;
namespace.controller = controller;
namespace.foo = bar; // Set other stuff here as well.

谢谢。出于某种原因,我没有想到使用命名空间,尽管我在其他地方正在使用它。 - John Topley

3

我认为这是一种不好的编程实践。如果必须要使用全局变量,你可以轻松地为应用程序创建一个命名空间,并将全局变量放在其中。


2

当您想调用一个未知名称的全局函数时,它们非常有用。

var funcName = "updateAns" + ansNum;
window[funcName]();

它们可以用于: a)在大多数情况下避免使用危险的eval。 b)避免对全局变量的引用错误。

x = x + 1 如果未定义全局x,则会生成引用错误。 window.x = window.x + 1 将不会。


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