如果这是重复的,请告诉我这是重复的。如何在多个函数中重用js闭包?似乎我无法弄明白,我可能会遗漏一些东西,但我要么必须重新实现内部函数(创建闭包),要么将函数放在外面(但是,它不再是闭包)。我如何同时做两件事?
示例:因此创建一个js闭包:
function a()
{
var x = "99";
var b = function()
{
//x=99
}
}
function z()
{
var x = "99";
var b = function()
{
//x=99
}
}
然而,这不是封闭:
function bTemplate()
{
//when coming from call of b() in m, x will not be the x from function m!
}
function m()
{
var x = "99";
var b = bTemplate;
b(); //x is not the x from function m
}
function n()
{
var x = "98";
var b = bTemplate;
b(); //x is not the x from function m
}
我的问题是:* 如何从外部定义函数(以避免重复),同时创建一个闭包,以便不必传入参数?也许这是非常明显的事情,但出于某种原因,无法弄明白。 *
例如上面,如果m和n是稍微不同的包装函数,那么如何在不将bTemplate作为内部函数实现的情况下捕获两者的状态?
谢谢!
答案 0 :(得分:2)
这是一种可能的方法:
function make_b(x) {
var b = function() {
//x come from argument to make_b
};
return b;
}
function a() {
var x = "99";
var b = make_b(x);
}
function z() {
var x = "99";
var b = make_b(x);
}
这允许您仅在一个位置定义函数b
,并且在a
和z
中都可以访问x
的值而不会传递到b
{1}}使用闭包。我认为这符合您的要求,但仍然有点不清楚为什么您不想将x
传递给b
。
答案 1 :(得分:1)
function Wrapper(){
var x = "99";
this.bTemplate = function()
{
//has access now to x because x is closed over by wrapper function
}
this.m = function()
{
var b = bTemplate;
b(); //x is now the same x as m because it is declared in Wrapper
}
}
答案 2 :(得分:1)
你可以通过以下方式解决问题:
function cl() {
var x = 99;
var funcs = {};
funcs.a = function() {
return x;
}
funcs.b = function() {
return 2*x;
}
return funcs;
}
theFuncs = cl();
theFuncs.a();
theFuncs.b();
答案 3 :(得分:1)
你完全错过了词汇范围的观点。
在您的示例中,函数a和b属于同一范围,因此每个函数都应该具有对另一个完全不可见的内部范围链。你尝试这样做的方式违反了JavaScript解释器的工作方式,因此如果不发明自己的DSL或其他东西就不可能。
你应该使用你的第二个例子。
答案 4 :(得分:1)
您可以利用隐式传递给函数的this
参数。但同样,它仍在“传递”某些东西,即使它没有被明确声明为参数。
function bTemplate()
{
// here use this.x
}
function m()
{
this.x = "99";
bTemplate.call(this);
}
function n()
{
this.x = "98";
bTemplate.call(this);
}
答案 5 :(得分:0)
我认为你们都是对的,我不能同时做到这两点。我必须要重新定义它,要么通过它。我想没有什么能阻止我确保内部函数将变量定义为自身的属性,然后通过函数调用将内部函数本身传递给外部模板函数,然后以这种方式捕获环境,如果我真的想拥有多个内部功能将自己传递到外部,这可能是唯一的方法吗?我想我现在明白了。谢谢!
示例:http://jsfiddle.net/BY3Kc/3/
HTML:
<div id="a"></div>
CSS:
$("#a").css({"width":500,"height":500,"border":"3px solid"});
function outsider(obj,cb)
{
console.log(obj.o);
cb();
}
$("#a").on("click",function(){
var that = arguments.callee;
that.o = "a";
outsider(that,function(){console.log("done")});
});
$("#a").on("dblclick",function(){
var that = arguments.callee;
that.o = "b";
outsider(that,function(){console.log("done2")});
});
答案 6 :(得分:0)
你做不到。这是词法范围的要点 - 变量的使用是指在词法封闭范围中定义的变量,即在源代码中物理包围它的范围。因此,您可以通过查看源代码来确定仅引用的变量。
因此,如果要在函数中使用变量x
,它必须是参数或局部变量,或者必须在词法周围的范围内定义。
如果您希望能够引用调用范围中的变量,则称为动态范围。动态范围很有趣,但不直观。历史上有些语言使用动态范围。今天没有常用的语言使用动态范围(Perl可以用来做动态范围,但默认情况下它仍然是词法范围)。
答案 7 :(得分:-1)
两种可能的解决方案。
一。使用有争议的eval()
。
function changeX() {
x += 40;
console.log(x);
}
function a() {
var x = 7;
eval(changeX.toString());
changeX();
}
两个。放下关闭的爱情。只需使用您喜欢的任何风格的“普通”对象。
function Closure() {
this.changeX = function() {
this.x += 40;
console.log(this.x);
}
}
function a() {
Closure.apply(this);
this.x = 1;
this.changeX();
}
function b() {
Closure.apply(this);
this.x = 2;
this.changeX();
}
function c() {
this.x = 3;
this.changeX();
}
c.prototype = new Closure();
...或者您更喜欢构建对象。
请记住,“正常”对象和闭包之间的唯一区别,至少与您的问题有关,就是在变量前面不存在this.
。
我个人建议使用方法二:只需构建对象并习惯于输入this.
和that.
。 eval()
完成工作,但这是有争议和不必要的。