在函数中更改变量并保持javascript?

时间:2012-03-12 05:32:50

标签: 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 = 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){ }并在我调用它时传递了正确的值。异步可能很痛苦:/

4 个答案:

答案 0 :(得分:1)

最简单的解决方案是将其移出np_handler函数。请注意,随后对该函数的调用将覆盖其值。

答案 1 :(得分:1)

我创建了一个包装器对象,并将您的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;
                }
            });
        }
    };
}

答案 2 :(得分:1)

设置方式,变量范围为np_handler。这意味着每次调用此函数时,您将获得一个新值(初始化为'')。

听起来你想要的是超出这个功能的东西,所以在Javascript中这很容易 - 只有功能或全局范围。因此删除teh 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;
  });
};

如果您不想使用全局变量,您可以将变量的范围放在其他位置,正如其他人指出的那样。

答案 3 :(得分:0)

有许多方法可以在函数调用中使变量保持不变。它们都涉及将变量声明或存储移动到函数范围之外,这样它就不会被重新创建,然后在每次函数运行时死掉。

功能的属性

一种更简单的方法是将其指定为np_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 = '';

全球范围

如果你想把它放在与函数相同的范围内,你可以在相同的范围内声明它,而不是像这样在本地声明它,但是如果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;
      }
    });
  }
};

全局命名空间对象

如果您需要全局访问它,但您不希望污染全局命名空间,或者您希望避免名称冲突的可能性,您可以创建一个全局命名空间对象并使全局变量是该对象的属性。然后,您可以将所有全局变量作为属性放在一个主全局对象上,并且只在全局空间中引入一个新名称而不是多个。你会这样做:

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