[英]Invoking jQuery function every x second (object literal pattern)
I'm trying to give my jQuery a bit more a structure with a basic object literal pattern and encountered an issue with calling my custom move
function as per the following. 我试图给我的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);
I'm trying to call this function every second but the calling part itself doesn't seem to work. 我试图每秒调用一次此函数,但是调用部分本身似乎不起作用。 I suspect that the variable
movingMenu
is maybe outside the scope that within window.setInterval
it doesn't have a clue in which object this function belongs to? 我怀疑变量
movingMenu
可能不在window.setInterval
范围内,它不知道此函数属于哪个对象?
The code you post here would not work, as you use an IIFE to wrap the object, the setInterval
can't access movingMenu
. 您在此处发布的代码无法正常工作,因为您使用IIFE包装对象,因此
setInterval
无法访问movingMenu
。 However, your code in jsfiddle is correct. 但是,您在jsfiddle中的代码是正确的。 You can either dewrap the IIFE, or put the
setInterval
into the IIFE, or return a object that exposed the move
function. 您可以解包IIFE,或将
setInterval
放入IIFE,或返回暴露了move
函数的对象。 You just need to ensure that movingMenu
, or the move
is accessible to setInterval
. 您只需要确保
movingMenu
或setInterval
可以访问此move
。
Use this
to get the ref of that menu in your function, as its an attribute
of movingMenu
, not an variable
. 使用
this
来获取函数中该菜单的引用,因为它是movingMenu
的attribute
,而不是variable
。
Move everything out of IIFE: 将所有内容移出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);
Move setInterval
into IIFE as well: 将
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);
})();
Yes, you are right, the variable movingMenu
is out of scope. 是的,您是对的,变量
movingMenu
不在范围内。
Also, to use the property menu
inside the method you need to use this.menu
. 另外,要在方法内部使用属性
menu
,您需要使用this.menu
。 There is no object scope in JavaScript, so even if you are "inside" the object, you can't directly access the object properties. 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);
})();
You're correct about movingMenu
being unavailable. 您对
movingMenu
不可用是正确的。 To get around this, you want to set your module to a variable and return whatever you want to access outside of the module. 为了解决这个问题,您需要将模块设置为变量,并返回要在模块外部访问的任何内容。
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);
edit: whoops, I read object literal pattern then saw the module pattern and ran in the wrong direction. 编辑:糟糕,我阅读了对象文字模式,然后看到了模块模式,并以错误的方向运行。
The scope of the movingMenu
object is limited to the anonymous function that wraps it... function() { var movingMenu = { ... } }
. movingMenu
对象的范围仅限于将其包装的匿名函数... function() { var movingMenu = { ... } }
。
You're using a syntax that is allowing you to define that anonymous function, and then invoke or call it immediately. 您使用的语法允许您定义该匿名函数,然后立即调用或调用它。
Declaration: (function() { var movingMenu = {..} })
声明:
(function() { var movingMenu = {..} })
Invocation: (function() { ... })()
调用:
(function() { ... })()
This would be the same as if you said... 就像你说的一样...
var foo = function() { var movingMenu = {...} };
foo();
So, in that context, movingMenu
is a variable that is defined inside another function, foo
. 因此,在这种情况下,
movingMenu
是在另一个函数foo
定义的变量。 Nothing oustide of foo
knows anything about movingMenu
. foo
一无所知对movingMenu
。 This is the idea of scope . 这就是范围的想法。
movingMenu
exists in the scope of foo
. movingMenu
存在于foo
的范围内。
So to get the functionality of movingMenu
outside the scope of foo
, we can return movingMenu
from foo
. 因此,
movingMenu
的功能超出foo
的范围,可以从foo
返回movingMenu
。 What this does is makes the return value of foo
the movingMenu
object, like so... 这样做是使
foo
的返回值成为movingMenu
对象,就像这样……
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()
Then, you can use menuHandler
like you would movingMenu
. 然后,您可以像
menuHandler
一样使用movingMenu
。
window.setInterval(function () {
menuHandler.move();
}, 1000);
Since you're declaring the function anonymously (not giving it a name, like I did with foo
), and then you're invoking it right away, you want to store the return value right away, since you won't be able to invoke that method again. 由于您要匿名声明该函数(不像我对
foo
那样给它起一个名字),然后立即调用它,因此您想立即存储返回值,因为您将无法再次调用该方法。
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()
Then, you can use menuHandler
like you were trying to use movingMenu
. 然后,您可以像尝试使用
menuHandler
一样使用movingMenu
。 Really, could use the name movingMenu
instead of menuHandler
, I just think it's less confusing this way. 确实,可以使用名称
movingMenu
代替menuHandler
,我只是认为这种方式不太容易混淆。
window.setInterval(function () {
menuHandler.move();
}, 1000);
So putting it altogether, with the anonymous function... 因此,将其与匿名功能放在一起...
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);
So why would you do this? 那为什么要这么做呢? Why not just make
movingMenu
public and invoke it directly, instead of wrapping it in an anonymous method and exposing it as a return value from that method? 为什么不只是将
movingMenu
公开并直接调用它,而不是将其包装在一个匿名方法中并作为该方法的返回值公开呢? The reason again has to do with scope. 原因再次与范围有关。 By limiting the scope and controlling what is exposed, you can actually create (somewhat, details are beyond the scope of this question) private properties in js.
通过限制范围并控制公开的内容,您实际上可以在js中创建(某种程度上,细节超出了此问题的范围)。
For example... 例如...
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;
})();
From this example, you can now see that movingMenu
is exposed (as menuHandler
), and it has the ability to use the private variable privateCounter
, however, privateCounter
is not exposed. 从此示例中,您现在可以看到
movingMenu
被公开(作为menuHandler
),并且具有使用私有变量privateCounter
的能力,但是privateCounter
没有公开。 So basically this pattern makes everything private initially, so you can expose just what you want to be public. 因此,基本上,此模式最初将所有内容设为私有,因此您可以公开想要公开的内容。
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>
NOTE In my snippet I've modified your code to make the menu
property non-static. 注意在我的代码段中,我已经修改了您的代码,以使
menu
属性变为非静态。 This will handle items being added or removed from the menu. 这将处理从菜单添加或删除的项目。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.