JS - 在外部函数外声明嵌套函数

时间:2018-02-12 09:03:12

标签: javascript function lexical-scope

案例1:我理解为什么它适用于这种情况:

function foo(arg) {
  var outer = " this is the outer variable";
  function bar() {
    console.log("arg: " + arg);
    console.log("outer variable: ", outer);
  }
  bar();
}

console.log(foo("hello"));

案例2:但我不明白为什么如果将bar函数分别声明为function foo(arg) { var outer = " this is the outer variable"; bar(); } function bar() { console.log("arg: " + arg); console.log("outer variable: ", outer); } console.log(foo("hello")); 函数,以下内容不起作用:

bar

案例3:如果我向function foo(arg) { var outer = " this is the outer variable"; bar(); } function bar(arg, outer) { console.log("arg: " + arg); console.log("outer variable: ", outer); } console.log(foo("hello")); 函数添加参数:

"arg: undefined"
"outer variable: " undefined

输出:

bar()

我的问题是关于案例2:为什么foo()没有达到bar(arg, outer)中定义的变量?

编辑案例2:

从所有反馈中吸取了教训,我在 bar(arg, outer); } function bar(arg, outer) { console.log("arg: " + arg); console.log("outer variable: ", outer); } console.log(foo("hello")); 添加了参数,并且它有效。非常感谢。     function foo(arg){       var outer ="这是外部变量&#34 ;;

{{1}}

有效。

7 个答案:

答案 0 :(得分:1)

功能参数仅在声明功能

中可见

因此bar函数无法访问foo's参数

您应该将参数传递给foo函数

function foo(arg) {
  var outer = " this is the outer variable";

  bar(arg); //<-------------
}

function bar(arg, outer) {
  console.log("arg: " + arg);
  console.log("outer variable: ", outer);
}

答案 1 :(得分:1)

因为bar的词法范围是由它在代码中的位置定义的,而不是它执行的链。让我引用维基百科的主题:

  

范围界定的一个根本区别是&#34;程序的一部分&#34;   手段。在具有词法范围的语言中(也称为静态范围),   名称解析取决于源代码中的位置和   词汇上下文,由命名变量或的位置定义   功能已定义。相比之下,在具有动态范围的语言中   名称解析取决于名称时的程序状态   遇到的是由执行上下文或调用确定的   上下文。

     

实际上,通过词法范围,可以解决变量的定义   搜索其包含的块或函数,然后如果失败   搜索外部包含块,依此类推,而使用动态   搜索调用函数的范围,然后是调用的函数   调用函数,等等,进入调用堆栈。[4]的   当然,在这两个规则中,我们首先寻找a的本地定义   变量

换句话说,如果您在bar内声明foo,其词汇范围将包括foo的词法范围。

答案 2 :(得分:1)

无论调用函数的位置,甚至调用它的方式,其词法范围由声明函数的位置定义。

function foo(arg) {
  var outer = " this is the outer variable";
  function bar() {
    console.log("arg: " + arg);
    console.log("outer variable: ", outer);
  }
  bar();
}

这里bar可以访问外部变量,因为它在词法范围内,但不在案例2中。

答案 3 :(得分:1)

我建议你阅读https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/var

The scope of a variable declared with var is its current execution context, which is either the enclosing function or, for variables declared outside any function, global.

outer封装在foo内,因此在该函数之外没有对它的引用。

尝试将其作为参数传递

var outer = 'global var';

function foo() {
  var inner = "this is the inner variable";
  bar(inner);
}

function bar(arg) {
  console.log("arg: " + arg);
  console.log("outer var: " + outer);
}

答案 4 :(得分:1)

  

bar 定义时,其范围链 已创建,预先加载   全局变量对象,并保存到内部[[Scope]]属性。   调用bar时,会创建执行上下文及其   范围链是通过复制函数中的对象来构建的   [[范围]]属性

所以,如果你给bar两个参数arg,outer,那就可以了:

function foo(arg) {
  var outer = " this is the outer variable";

  bar();
}

function bar(arg,outer) {
  console.log("arg: " + arg);
  console.log("outer variable: ", outer);
}

console.log(foo("hello"));
  

适用于Web Developers的专业JavaScript。3rd.Edition.Jan.2012

P222

答案 5 :(得分:0)

  

我的问题是关于案例2:为什么bar()没有达到   在foo()中定义的变量?

outer被声明为 var ,这意味着它具有功能范围(在中可以访问宣布)。

因此,在foo之外(在bar中),外部无法访问,除非它在bar或其父范围中声明(其中的功能)宣布bar

来自评论

  

我假设嵌套函数可以达到内部定义的变量   外部功能。

  • 混淆似乎源于bar嵌套在foo - 错误中的想法。

  • bar不属于foo ,因为它未在foo 中声明,因此声明的范围与{{1}相同}}

答案 6 :(得分:0)

你没有将必要的参数传递给bar函数,第三个未定义是因为你没有在函数中返回任何内容,这将起作用:

function bar(arg, outer) {
  console.log("arg: " + arg);
  console.log("outer variable: ", outer);
  return arg + outer;
}

function foo(arg) {
  var outer = " this is the outer variable";

  return bar(arg, outer);
}

console.log(foo("hello"));