【问题标题】:Change variable in function and keep it javascript?更改函数中的变量并保留它的javascript?
【发布时间】:2012-03-12 05:32:49
【问题描述】:

我怎样才能这样写,以便 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){ } 并在我调用它时传递了正确的值。异步可能很痛苦:/

【问题讨论】:

    标签: javascript node.js scope


    【解决方案1】:

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

    【讨论】:

    • 几乎总是。然而,在 Javascript 中,处理函数之外的应用程序结构将决定它是否实际上是全局的。如果处理程序包含在其他闭包中,则在 that 函数中声明变量可能是合适的(方便的)。
    • 好点,我猜。我现在采取什么方式并不重要,因为它是异步的,我不需要它。获取数据比尝试使用它需要更长的时间。我想我可以将其余的代码移到一个函数中并以完全不同的方式来做,我认为我别无选择,真的。
    【解决方案2】:

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

    【讨论】:

      【解决方案3】:

      按照您的设置方式,变量的范围为np_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;
        });
      };
      

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

      【讨论】:

        【解决方案4】:

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

        函数的属性

        一种更简单的方法是将其分配为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;
              }
            });
          }
        };
        

        【讨论】:

          猜你喜欢
          • 2014-03-10
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2020-05-11
          • 1970-01-01
          • 1970-01-01
          • 2022-12-04
          • 2021-05-08
          相关资源
          最近更新 更多