使用 apply 方法调用 jQuery document.ready 处理程序?

发布于 2024-11-15 00:50:24 字数 781 浏览 5 评论 0原文

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

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

    var onReadyCallback = function(){
        jQuery(文档).ready(函数(){
           if(!this.loggedIn()){
              返回;
           }
           ...很多代码使用“this”引用 MyNameSpace
    
        }.apply(MyNameSpace));
    };
    
    //加载需要的附加文件并触发onReadyCallback
    MyNameSpace.Util.loadFiles(defaultJsFiles,function(){ 
        MyNameSpace.Util.require(['My.App','My.Theme','My.DomHandler'], function(){
           onReadyCallback.apply(窗口);          
        });
    });
    

Below is the code I am using in a project with some complex dependencies. After I have made sure that all the dependencies have been loaded I fire the onReadyCallback() also given below. I have two questions :

  1. Is it correct to use, anonymousHandler.apply(MyNameSpace), the apply method on an anonymous Handler being called for Document.ready
  2. From what I understand, because I am using the apply method the anonymous function will fire immediately irregardless of document's ready state. Then how can I pass in the context of MyNameSpace to the anonymousHandler so that "this" inside the function refers to 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);          
        });
    });
    

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

べ繥欢鉨o。 2024-11-22 00:50:24

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

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

How about this, using an anonymous function and call?

jQuery(document).ready(function() {
    (function() {
        // this == MyNamespace
    }).call(MyNamespace);
});
差↓一点笑了 2024-11-22 00:50:24

通常,ready 事件 jQuery 函数会像下面这样调用。

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

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

一般来说,这些函数中的每一个都会在所有内容加载完成后调用,但不一定。在您的情况下,在 ready 事件发生之前有一个对 MyNameSpace 的引用。即使Javascript是LALR类型的语言,并且它会找到稍后声明的符号,这这不是一个好的做法。如果稍后在 jQuery 触发 ready 回调函数之前将 MyNameSpace 设置为其他内容会怎样?您的 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. ...在编辑源代码等

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

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

Normally, the ready event jQuery function is called like this

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

Bottom line, the function is not given a particular context; the actual context given by jQuery to the function is the HTMLDocument element, regardless of the argument (in the last example, document). Why is this so is another subject.

Generally, each of these functions are called later, after everything has been loaded, but not necessarily. In your case, there is a reference to MyNameSpace before the ready event happens. Even if Javascript is a LALR-type language, and it will find the symbol declared later, this is not a good practice. What if MyNameSpace would be set to something else later on, before jQuery triggers the ready callback functions? Your ready callback would not get that new reference. Unless intentional, the reference should be made inside the ready callback, when everything is.... ready.

Then, inside the ready callback, there are other techniques to assign a context to a function. lonesomeday have pretty much given the correct way to accomplish what you are trying to do.

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

The above code executes an anonymous function right away, where this == MyNameSpace

note : the difference between apply and call is decribed here

Now, comes the bottom part of the code you provided :

//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);          
    });
});

This is problematic, and unnecessary. Is the function onReadyCallback only needed there, or will it be called several times? If it needs to be called only once, spare the global namespace, and simply do :

//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`

       });
    });
});

If you don't like the indentation (it's merely a developer's taste), replace everything in the ready callback with (something like) :

 initMyNameSpace.apply(MyNameSpace);

and create your function outside, on the global space :

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

 };

But I would recommand, at least, to put it in the require callback function so it...

  1. ...does not pollute the global namespace with a run-once function
  2. ...is not accessible from anywhere (keep it private)
  3. ...can be found quickly when editing the source code
  4. etc.

note : usually, apply and call are used to avoid repeatedly accessing objects like some.thing.pretty.deep = value; or when one function needs to be applied to many but not all objects, and thus extending the object's prototype is just not a good idea.

This is my opinion anyway, and how I would do things, without any more knowledge of your code or what you are doing.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文