更改函数中的变量并将其保留为javascript?

更改函数中的变量并将其保留为javascript?,javascript,node.js,scope,Javascript,Node.js,Scope,我如何编写它,以便lfmuser保留在UserModel.find()调用的函数中所做的更改?如果可以避免的话,我真的不想在每个块中移动很大一部分代码 var np_handler = function (act) { var lfmuser = ''; if (act.params.length === 0) { UserModel.find({ nick: act.nick }, function (err, data) { if (!data) {

我如何编写它,以便lfmuser保留在
UserModel.find()调用的函数中所做的更改?如果可以避免的话,我真的不想在每个块中移动很大一部分代码

var np_handler = function (act) {
  var lfmuser = '';
  if (act.params.length === 0) {
    UserModel.find({ nick: act.nick }, function (err, data) {
      if (!data) {
        lfmuser = act.nick;
      } else {
        lfmuser = data.lastfm;
      }
    });
  } else {
    UserModel.find({ nick: act.params[0] }, function (err, data) {
      if (!data) {
        lfmuser = act.params[0];
      } else {
        lfmuser = data.lastfm;
      }
    });
  }
};

在这种情况下,结果并不重要,我只是将代码的其余部分(在我使用lfmuser的地方)移动到它自己的函数
np(lfm,act){}
,并在调用它时传递正确的值。异步可能是一个难题:/

最简单的解决方案是将它移到
np\u处理程序
函数之外。请注意,随后对函数的调用将覆盖其值。

我创建了一个包装器对象,并将lfmuser变量列为该对象的属性。它不是全局的,它的值将在函数完成执行后保持不变

var np_handler_object = {
    lfmuser = '',  // variable in scope of the np_handler object and persists

    np_handler: function (act) {

        if (act.params.length === 0) {
            UserModel.find({ nick: act.nick }, function (err, data) {
                if (!data) {
                    np_handler_object.lfmuser = act.nick;
                } else {
                    np_handler_object.lfmuser = data.lastfm;
                }
            });
        } else {
            UserModel.find({ nick: act.params[0] }, function (err, data) {
                if (!data) {
                    np_handler_object.lfmuser = act.params[0];
                } else {
                    np_handler_object.lfmuser = data.lastfm;
                }
            });
        }
    };
}

有许多方法可以使变量在函数调用之间持久化。它们都涉及将变量声明或存储移到函数作用域之外,这样就不会在每次函数运行时重新创建变量声明或存储,然后就消失了

函数的性质 一种简单的方法是将其作为
np\u handler()
函数的属性进行分配。这可以防止任何全局名称空间污染或冲突,但只要使用它的函数存在,它就会一直存在。可以这样做:

var np_handler = function (act) {
  if (act.params.length === 0) {
    UserModel.find({ nick: act.nick }, function (err, data) {
      if (!data) {
        np_handler.lfmuser = act.nick;
      } else {
        np_handler.lfmuser = data.lastfm;
      }
    });
  } else {
    UserModel.find({ nick: act.params[0] }, function (err, data) {
      if (!data) {
        np_handler.lfmuser = act.params[0];
      } else {
        np_handler.lfmuser = data.lastfm;
      }
    });
  }
};

// initialize
np_handler.lfmuser = '';
// make sure myGlobals is defined and assign a property to it
var myGlobals = myGlobals || {};
myGlobals.lfmuser = '';

var np_handler = function (act) {
  if (act.params.length === 0) {
    UserModel.find({ nick: act.nick }, function (err, data) {
      if (!data) {
        myGlobals.lfmuser = act.nick;
      } else {
        myGlobals.lfmuser = data.lastfm;
      }
    });
  } else {
    UserModel.find({ nick: act.params[0] }, function (err, data) {
      if (!data) {
        myGlobals.lfmuser = act.params[0];
      } else {
        myGlobals.lfmuser = data.lastfm;
      }
    });
  }
};
全球范围 如果您想将其放入与函数相同的作用域中,您可以在相同的作用域中声明它,而不是像这样在本地声明它,尽管如果np_handler位于全局作用域中,您现在在全局作用域中又有一个项目,您通常会尽量避免:

var lfmuser = '';

var np_handler = function (act) {
  if (act.params.length === 0) {
    UserModel.find({ nick: act.nick }, function (err, data) {
      if (!data) {
        lfmuser = act.nick;
      } else {
        lfmuser = data.lastfm;
      }
    });
  } else {
    UserModel.find({ nick: act.params[0] }, function (err, data) {
      if (!data) {
        lfmuser = act.params[0];
      } else {
        lfmuser = data.lastfm;
      }
    });
  }
};
全局命名空间对象 如果您需要全局可访问,但又不想对全局名称空间造成超出要求的污染,或者希望避免名称冲突的可能性,则可以创建一个全局名称空间对象,并使全局变量成为该对象的属性。然后,您可以将所有全局对象作为属性放在一个主全局对象上,并且在全局空间中只引入一个新名称,而不是多个。您可以这样做:

var np_handler = function (act) {
  if (act.params.length === 0) {
    UserModel.find({ nick: act.nick }, function (err, data) {
      if (!data) {
        np_handler.lfmuser = act.nick;
      } else {
        np_handler.lfmuser = data.lastfm;
      }
    });
  } else {
    UserModel.find({ nick: act.params[0] }, function (err, data) {
      if (!data) {
        np_handler.lfmuser = act.params[0];
      } else {
        np_handler.lfmuser = data.lastfm;
      }
    });
  }
};

// initialize
np_handler.lfmuser = '';
// make sure myGlobals is defined and assign a property to it
var myGlobals = myGlobals || {};
myGlobals.lfmuser = '';

var np_handler = function (act) {
  if (act.params.length === 0) {
    UserModel.find({ nick: act.nick }, function (err, data) {
      if (!data) {
        myGlobals.lfmuser = act.nick;
      } else {
        myGlobals.lfmuser = data.lastfm;
      }
    });
  } else {
    UserModel.find({ nick: act.params[0] }, function (err, data) {
      if (!data) {
        myGlobals.lfmuser = act.params[0];
      } else {
        myGlobals.lfmuser = data.lastfm;
      }
    });
  }
};

按照设置方式,变量的作用域为
np\u handler
。这意味着每次调用此函数时,都会得到一个新值(初始化为“”)

听起来您想要的是这个函数之外的持久性,所以在Javascript中这很容易——只有函数或全局作用域。所以删除
var lfmuser=''
行应该可以做您想要的事情

顺便说一句,当您使用时,一个局部变量和“?:”的使用会缩短代码,例如:

var lfmuser = '';
...

var np_handler = function (act) {
  var nick = act.params.length ? act.params[0] : act.nick;
  UserModel.find({ nick: nick }, function (err, data) {
    lfmuser = data ? data.lastfm : nick;
  });
};

如果您不想使用全局变量,您可以像其他人指出的那样,在其他地方定义变量的范围。

几乎总是这样。然而,在Javascript中,处理函数之外的应用程序的结构将决定它是否实际上是全局的。如果处理程序包含在某个其他闭包中,那么在该函数中声明变量可能是合适的(有利的)。我现在用什么方式做并不重要,因为它是异步的,我不需要它。抓取数据比尝试使用数据花费的时间更长。我想我可以把剩下的代码移到一个函数中,然后完全不同地完成它,我真的觉得我没有选择的余地。