代码之家  ›  专栏  ›  技术社区  ›  Seong Lee

每x秒调用jQuery函数(对象文本模式)

  •  0
  • Seong Lee  · 技术社区  · 9 年前

    我试图给jQuery提供一个具有基本对象文字模式的结构,但在调用自定义时遇到了问题 move 功能如下。

    (function() {
    
      var movingMenu = {
        menu: $('.nav').children('li'),
    
        move: function() {
          menu.each(function() {
            $(this).animate({
                top: '+=50'
            }, 200);
          });   
        }
      };  
    
    })();
    
    window.setInterval(function(){
      movingMenu.move();
    }, 1000);
    

    我试图每秒调用一次这个函数,但调用部分本身似乎不起作用。我怀疑变量 movingMenu 可能超出了范围 window.setInterval 它不知道这个函数属于哪个对象?

    演示可用 JSFiddle

    4 回复  |  直到 9 年前
        1
  •  5
  •   fuyushimoya    9 年前
    1. 您在这里发布的代码不起作用,因为您使用IIFE包装对象 setInterval 无法访问 movingMenu 。然而,jsfiddle中的代码是正确的。你可以解开IIFE,或者把 setInterval(设置间隔) 或返回一个暴露 move 作用你只需要确保 移动菜单 ,或 移动 可以访问 setInterval(设置间隔) .

    2. 使用 this 获取函数中该菜单的引用,因为它是 attribute 属于 移动菜单 ,不是 variable .

    改变了的 jsfiddle

    将所有内容移出IIFE:

    var movingMenu = {
        menu: $('.nav').children('li'),
    
        move: function () {
        //  VVVV you need to use this to reference to `movingMenu`, so this.menu is the referenced `li`s.
            this.menu.each(function () {
                $(this).animate({
                    top: '+=50'
                }, 200);
            });
        }
    };
    
    window.setInterval(function () {
        movingMenu.move();
    }, 1000);
    

    移动 setInterval(设置间隔) 同时也纳入IIFE:

    (function(){
        var movingMenu = {
            menu: $('.nav').children('li'),
    
            move: function () {
            //  VVVV you need to use this to reference to `movingMenu`, so     this.menu is the referenced `li`s.
                this.menu.each(function () {
                    $(this).animate({
                        top: '+=50'
                    }, 200);
                });
            }
        };
    
        window.setInterval(function () {
            movingMenu.move();
        }, 1000);
    })();
    
        2
  •  2
  •   Guffa    9 年前

    是的,你是对的,变量 movingMenu 超出范围。

    此外,要使用属性 menu 在您需要使用的方法中 this.menu 。JavaScript中没有对象作用域,因此即使您在对象内部,也无法直接访问对象属性。

    (function() {
    
      var movingMenu = {
        menu: $('.nav').children('li'),
    
        move: function() {
          // use "this" to access properties
          this.menu.each(function() {
            $(this).animate({
                top: '+=50'
            }, 200);
          });   
        }
      };  
    
      // use the variable inside the scope
      window.setInterval(function(){
        movingMenu.move();
      }, 1000);
    
    })();
    
        3
  •  1
  •   bcr    9 年前

    你说得对 movingMenu 不可用。为了解决这个问题,您需要将模块设置为一个变量,并返回模块外部要访问的任何内容。

    var movingMenu = (function() {
    
      return {
        menu: $('.nav').children('li'),
    
        move: function() {
          this.menu.each(function() {
            $(this).animate({
                top: '+=50'
            }, 200);
          });   
        }
      };
    
    })();
    
    window.setInterval(function(){
      movingMenu.move();
    }, 1000);
    

    编辑:哇,我读了对象文本模式,然后看到了模块模式,并朝着错误的方向运行。

        4
  •  -1
  •   Eric Lease    9 年前

    movingMenu 对象仅限于包装它的匿名函数。。。 function() { var movingMenu = { ... } } .

    您使用的语法允许您定义匿名函数,然后立即调用或调用它。

    宣言: (function() { var movingMenu = {..} })

    调用: (function() { ... })()

    这和你说的一样。。。

    var foo = function() { var movingMenu = {...} };
    foo();
    

    因此,在这种情况下, 移动菜单 是在另一个函数内定义的变量, foo .没有什么可取代的 食品 什么都知道 移动菜单 这是 scope . 移动菜单 存在于的范围内 食品 .

    因此,要获得 移动菜单 超出 食品 ,我们可以回来 移动菜单 从…起 食品 。它的作用是使 食品 这个 移动菜单 对象,就像这样。。。

    var foo = function() { 
        var movingMenu = {
            menu: $('.nav').children('li'),
    
            move: function() {
              menu.each(function() {
                $(this).animate({
                   top: '+=50'
                },200);
              });   
            }
          };
    
          return movingMenu;  
    
        };
    
    var menuHandler = foo(); // save movingMenu, returned from foo()
    

    然后,您可以使用 menuHandler 就像你一样 移动菜单 .

    window.setInterval(function () {
       menuHandler.move();
    }, 1000);
    

    因为你是匿名声明函数(而不是像我那样给它命名) 食品 ),然后立即调用它,您希望立即存储返回值,因为您将无法再次调用该方法。

    var foo=函数(){
    var移动菜单={
    菜单:$('.nav').childs('li'),
    
    移动:函数(){
    菜单每个(函数){
    $(this).animate({
    顶部:'+=50'
    },200);
    });
    }
    };
    
    返回移动菜单;
    
    };
    
    var menuHandler=foo();//save movingMenu,从foo()返回
    

    然后,您可以使用 菜单处理程序 就像你试图使用 移动菜单 。真的,可以用这个名字 移动菜单 而不是 菜单处理程序 ,我只是觉得这样比较不容易混淆。

    窗setInterval(函数(){
    menuHandler.move();
    }, 1000);
    

    总之,使用匿名函数。。。

    var menuHandler = (function() { 
        var movingMenu = {
            menu: $('.nav').children('li'),
    
            move: function() {
              menu.each(function() {
                $(this).animate({
                   top: '+=50'
                },200);
              });   
            }
          };
    
          return movingMenu;  
    
        })();
    
    window.setInterval(function () {
       menuHandler.move();
    }, 1000);
    

    那你为什么要这样做?为什么不做 移动菜单 public并直接调用它,而不是将其包装在匿名方法中并将其作为该方法的返回值公开?原因再次与范围有关。通过限制范围和控制公开的内容,您实际上可以在js中创建(在某种程度上,细节超出了这个问题的范围)私有属性。

    例如

    var menuHandler = (function() {
        // ADDED NEXT LINE FOR EXAMPLE:
        var privateCounter = 0; 
        var movingMenu = {
            menu: $('.nav').children('li'),
    
            move: function() {
              menu.each(function() {
                $(this).animate({
                   top: '+=50'
                },200);
    
                // ADDED NEXT LINE FOR EXAMPLE:
                console.log("Count is now: " + (privateCounter++).toString());
                // look at the console tab of browser's dev tools (F-12 on windows)
              });   
            }
          };
    
          return movingMenu;  
    
        })();
    

    从这个例子中,您现在可以看到 移动菜单 暴露(如 菜单处理程序 ),并且它能够使用私有变量 privateCounter 然而 私人计数器 未暴露。因此,基本上,这种模式最初使所有内容都是私有的,因此您可以公开您想要公开的内容。

    var menuHandler = (function() {
      var privateCounter = 0,
        menu = (function() {
          return $('.nav').children('li');
        })();
    
      var movingMenu = {
        move: function() {
          menu.each(function() {
            $(this).animate({
              top: '+=50'
            }, 200);
          });
    
          console.log("Count is now: " + (privateCounter++).toString());
        }
      };
    
      return movingMenu;
    })();
    
    setInterval(function() {
      menuHandler.move();
    }, 1000);
    .nav {
      position: absolute;
    }
    .nav li {
      position: relative;
      top: 0;
    }
    ul {
      list-style: none;
    }
    ul li {
      display: inline-block;
      background: red;
      border-radius: 50%;
      color: white;
      width: 50px;
      height: 50px;
      text-align: center;
      line-height: 3;
    }
    <ul class="nav">
      <li>Look</li>
      <li>Play</li>
      <li>Eat</li>
      <li>See</li>
    </ul>

    注释 在我的代码段中,我修改了您的代码 menu 属性非静态。这将处理从菜单中添加或删除的项目。