2

下面是我在具有一些复杂依赖项的项目中使用的代码。在确保所有依赖项都已加载后,我触发了下面给出的onReadyCallback()。我有两个问题:

  1. 使用 anonymousHandler.apply(MyNameSpace) 是否正确,为 Document.ready 调用匿名处理程序上的 apply 方法
  2. 据我了解,因为我使用的是 apply 方法,所以无论文档的就绪状态如何,匿名函数都会立即触发。那么如何在MyNameSpace的上下文中传递给anonymousHandler以便函数内的“this”引用 MyNameSpace

    var onReadyCallback = function(){
        jQuery(document).ready(function(){
           if(!this.loggedIn()){
              return;
           }
           ...Lots of Code referring to MyNameSpace using "this"
    
        }.apply(MyNameSpace));
    };
    
    //load the additional files that are needed and fire onReadyCallback
    MyNameSpace.Util.loadFiles(defaultJsFiles,function(){ 
        MyNameSpace.Util.require(['My.App','My.Theme','My.DomHandler'], function(){
           onReadyCallback.apply(window);          
        });
    });
    
4

2 回答 2

4

这个怎么样,使用匿名函数和call

jQuery(document).ready(function() {
    (function() {
        // this == MyNamespace
    }).call(MyNamespace);
});
于 2011-06-08T16:31:03.003 回答
1

通常,ready事件 jQuery 函数是这样调用的

$(function() { /* ... */ });
// or 
jQuery(function() { /* ... */ });
// or
jQuery(document).ready(function() { /* ... */ });

最重要的是,该函数没有给出特定的上下文;jQuery 为函数提供的实际上下文是HTMLDocument元素,与参数无关(在最后一个示例中,document)。为什么会这样是另一个话题。

通常,这些函数中的每一个都会在加载完所有内容之后调用,但不一定。在您的情况下,在事件发生MyNameSpace之前有一个参考。ready即使 Javascript 是一种LALR类型的语言,并且它会找到稍后声明的符号,这也不是一个好习惯。如果MyNameSpace稍后在 jQuery 触发ready回调函数之前设置为其他内容怎么办?您的ready回调不会得到那个新的参考。除非有意,否则应该在回调内部ready进行引用,当一切都准备好时。

然后,在ready回调内部,还有其他技术可以将上下文分配给函数。lonesomeday几乎给出了正确的方法来完成你想做的事情。

(function() {
    // this == MyNamespace
}).call(MyNamespace);

上面的代码立即执行了一个匿名函数,其中this == MyNameSpace

注意:此处描述了applycall之间的区别

现在,是您提供的代码的底部:

//load the additional files that are needed and fire onReadyCallback
MyNameSpace.Util.loadFiles(defaultJsFiles,function(){ 
    MyNameSpace.Util.require(['My.App','My.Theme','My.DomHandler'], function(){
       onReadyCallback.apply(window);          
    });
});

这是有问题的,也是不必要的。该函数是否onReadyCallback只需要在那里,还是会被多次调用?如果只需要调用一次,请保留全局命名空间,只需执行以下操作:

//load the additional files that are needed and fire onReadyCallback
MyNameSpace.Util.loadFiles(defaultJsFiles,function(){ 
    MyNameSpace.Util.require(['My.App','My.Theme','My.DomHandler'], function(){

       // if everything is done loading, the function will be executed, otherwise
       // it's execution will be postponed later
       jQuery(function() {

           // create our nicely wrapped anonymous function now
           (function() {
              if(!this.loggedIn()){
                 return;
              }
              // ...Lots of Code referring to MyNameSpace using "this"

           })(MyNameSpace);  // grab our most recent reference of `MyNameSpace`

       });
    });
});

如果您不喜欢缩进(这只是开发人员的口味),请将ready回调中的所有内容替换为(类似):

 initMyNameSpace.apply(MyNameSpace);

并在全局空间之外创建您的函数:

 function initMyNameSpace() {
    if(!this.loggedIn()){
       return;
    }
    // ...Lots of Code referring to MyNameSpace using "this"

 };

但我建议,至少,把它放在require回调函数中,这样它......

  1. ...不会使用一次性运行函数污染全局命名空间
  2. ...无法从任何地方访问(保密)
  3. ...在编辑源代码时可以快速找到
  4. 等等

注意:通常,applycall用于避免重复访问对象,例如some.thing.pretty.deep = value;或者当一个函数需要应用于许多但不是所有对象时,因此扩展对象的原型并不是一个好主意。

无论如何,这是我的意见,以及我将如何做事,而无需更多地了解您的代码或您在做什么。

于 2011-06-08T17:41:22.063 回答