【问题标题】:If a variable is created within the scope of a function that returns a function that uses that variable. Is it possible to acces that variable outside如果在返回使用该变量的函数的函数范围内创建变量。是否可以在外部访问该变量
【发布时间】:2022-02-08 07:29:58
【问题描述】:
function creatPrintNumFunction()
{
  var num= 12;
  return function printNum()
  {
     console.log(num);
  }
}

 var printer = creatPrintNumFunction();
printer.num =13; //this part doesn't work but is there a way to access this Num variable Outside the creatPrintNumFunction, The printer function must be finding the num variable from somewhere.
printer();

那么我怎样才能让这段代码打印 13 而不是 12最重要的是不更改 createPrintNumFunction() 的任何代码。

有关我真正需要使用该理论的更多背景信息。我在 node.js 中使用了一个我不想更改的外部模块 express-sessions。有一个“存储”变量,所有会话都存储在其中,我需要访问唯一的问题是它是在函数中创建的。还有另一种方法可以访问它,但它不是很方便

【问题讨论】:

  • 就目前而言,您的代码不使用num 局部变量;它打印未定义的store 全局变量。我怀疑您在发布问题时过度简化了代码。
  • 对不起,我编辑修复这是一个分散注意力的错误
  • 使用您显示的代码,无法从creatPrintNumFunction 函数外部修改num 局部变量。
  • 是的,现在我知道我想要做的事情是不可能的,谢谢

标签: javascript node.js


【解决方案1】:

寻找这样的东西?

function creatPrintNumFunction() {
  const f = function printNum() {
    console.log(f.num);
  };
  f.num = 12;           // set .num property to initial value
  return f;             // return function "printNum"
}

var printer = creatPrintNumFunction();
printer.num = 13;
printer();

printer.num = 42;
printer();

【讨论】:

  • 这涉及更改 creatPrintNumFunction() 中的代码,我想避免更改但我可能会更改它,
【解决方案2】:

有一个“存储”变量,其中存储了我需要访问的所有会话,唯一的问题是它是在函数中创建的。还有另一种方法可以访问它,但它不是很方便

不,不修改代码就无法访问store。而且您不应该修改外部模块的代码,因为store 可能由于某种原因而无法访问。更改代码可能会导致代码库阻止您更新express-sessions

需要这样做听起来像是一个 XY 问题。


如果它是您的代码,并且您希望允许访问该变量,则有不同的方法可以做到这一点。您肯定可以将var num 移到creatPrintNumFunction 之外(如answer of alonealgorithm 中所述,但这会破坏您之前的封装。这是否是一个好主意取决于实际用例。但您需要请注意,如果您这样做,则从 creatPrintNumFunction 返回的每个“打印”函数都会使用相同的变量。

假设您不想将num 移出creatPrintNumFunction 的范围,因为从creatPrintNumFunction 返回的每个“打印”函数都应该有自己的num 变量。

然后您可以做的是在creatPrintNumFunction 中创建另一个函数(例如set),该函数可以更改num,并将此函数作为属性分配给您从creatPrintNumFunction 返回的函数。

function creatPrintNumFunction() {
  var num = 12;
  
  // both "set" and "printNum" create here
  // have a closure over the same "num" variable
  function set(val) {
    num = val;
  }

  function printNum() {
    console.log(num);
  }

  // the "set" function is assigned as a parameter to your
  // printNum function
  printNum.set = set;

  return printNum;
}

var printerA = creatPrintNumFunction();
var printerB = creatPrintNumFunction();
printerA.set(13)
printerB.set(23)
printerA();
printerB();

这种方法的优点是您不会暴露num,并且您可以在set 函数中控制如何/是否可以更改num

【讨论】:

  • 感谢您使用的方法虽然仍然修改了我想避免的 creatPrintNumFunction() 函数的内容,但单独的算法似乎很确定没有办法做我想做的事情而不改变creatPrintNumFunction() 所以我会相信他。
  • @Cavernhead 是的,如果不更改代码,就无法访​​问num。如果express-session 的作者选择使其无法访问,那么这样做是有原因的。一个原因可能是他们不想对store 的外观做出任何保证,因此只允许通过 API 访问它。
【解决方案3】:

所以,你写的关于 printNum() 函数能够以某种方式访问​​ num 变量的评论是由于 JavaScript 闭包。闭包是一个重要的 JavaScript 主题,我建议您查看一些在线资源或此 stackoverflow 帖子 JavaScript closures 来了解。本质上,当您从 createPrintNumFunction 返回 printNum 函数时,printNum 函数将记住在 createPrintNumFunction 中声明的 num 变量。但是要回答您是否可以在声明的范围之外访问变量的问题,那么答案是否定的。外部作用域不能从内部作用域访问变量。内部作用域可以从外部作用域访问变量。因此,除非您在声明的范围之外跟踪 num 变量,否则您将无法访问在声明的范围之外的 num 持有的值。

因此,您可以在此处更改 printNum 函数本身的 num 的值,如下所示:

function creatPrintNumFunction() {
  var num = 12;
  return function printNum() {
    num = 13;
    console.log(num);
  };
}

var printer = creatPrintNumFunction();
printer.num = 13; //this part doesn't work but is there a way to access this Num variable Outside the creatPrintNumFunction, The printer function must be finding the num variable from somewhere.
printer();

您可以定义一个跟踪num 变量的全局变量。然后通过作用域链,在 printNum 函数内部为 num 变量使用的值将解析为您的全局变量当前包含的值,如下所示:

var num = 12;

function creatPrintNumFunction() {
  return function printNum() {
    console.log(num);
  };
}

var printer = creatPrintNumFunction();
num = 13; //this part doesn't work but is there a way to access this Num variable Outside the creatPrintNumFunction, The printer function must be finding the num variable from somewhere.
printer();

我确信还有其他方法可以解决这个问题,但我希望上述方法之一适合您的需要。

【讨论】:

  • 非常感谢,特别是指导我了解 JavaScript 闭包的解释。我觉得有很多关于 javascript 的基本语言内容我不了解,这阻碍了我了解 node.js 的许多模块是如何工作的。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-06-01
  • 2018-08-16
  • 2014-05-29
  • 2019-10-05
  • 1970-01-01
  • 2015-09-04
相关资源
最近更新 更多