javascript命名函数表达式-作用域可访问性

javascript命名函数表达式-作用域可访问性,javascript,function,Javascript,Function,我在跟踪,我发现了一些我不清楚的地方。以下代码定义了命名函数表达式: 正如我所看到的,在当前范围内(假设它是全局的),ninja是保存对命名函数myNinja的引用的变量ninja变量在作用域中是可访问的-这很清楚,但是myNinja在作用域中是不可访问的(但它可以在自己的函数中访问)。为什么 如果我定义了一个函数(不是使用函数表达式,而是使用函数声明): 然后在当前范围内可以访问它。我知道它就是这样工作的——但有人能解释为什么会这样吗?想象一下,当你简单地定义一个函数(cheese)时,你告诉

我在跟踪,我发现了一些我不清楚的地方。以下代码定义了命名函数表达式:

正如我所看到的,在当前范围内(假设它是全局的),
ninja
是保存对命名函数
myNinja
的引用的变量
ninja
变量在作用域中是可访问的-这很清楚,但是
myNinja
在作用域中是不可访问的(但它可以在自己的函数中访问)。为什么

如果我定义了一个函数(不是使用函数表达式,而是使用函数声明):


然后在当前范围内可以访问它。我知道它就是这样工作的——但有人能解释为什么会这样吗?

想象一下,当你简单地定义一个函数(cheese)时,你告诉当前的范围——“我想让你知道这个函数,它的名字是cheese。 当你使用var ninja时,你现在处理的是ninja范围,告诉它基本上是一样的。所以现在你只知道当前(ninja)范围内的新函数(myNinja…

在他的书中,John Resig对这个概念做了精彩的解释

以下是该书的引文:

4.2.4.内联命名函数

 <script type="text/javascript">
  var ninja = function myNinja(){ 
      assert(ninja == myNinja, "this is named two things at once!"); 
  };
  ninja(); 
  assert(typeof myNinja == "undefined",
    "But myNinja isn't defined outside of the function."); 
 </script>

var ninja=函数myNinja(){
断言(ninja==myNinja,“这是同时命名的两个东西!”);
};
忍者();
断言(myNinja的类型==“未定义”,
“但是myNinja不是在功能之外定义的。”);
这个清单提出了关于内联的最重要的一点 函数:尽管内联函数可以命名,但这些名称是 仅在函数本身中可见

还记得我们在第3章中讨论的范围规则吗?Inline 函数名的行为有点像变量名,它们的作用域是 仅限于声明它们的函数。

3.2.1.范围和功能

 <script type="text/javascript">
  var ninja = function myNinja(){ 
      assert(ninja == myNinja, "this is named two things at once!"); 
  };
  ninja(); 
  assert(typeof myNinja == "undefined",
    "But myNinja isn't defined outside of the function."); 
 </script>
变量声明从声明点到 声明它们的函数的结尾,无论 块嵌套

如果你想更多地了解这个概念,这本书将帮助你

为什么呢

函数表达式每次求值时都会创建一个新的函数对象。该结果的结果起初并不相关。但是

var ninja;
// myNinja; - what would you expect it to be here?
for (var i=0; i<5; i++)
    ninja = function myNinja(){
        console.log(myNinja);
    };
// myNinja; - *which one* would you expect it to be here?
ninja();
var忍者;
//我的忍者;-你希望它在这里是什么?

for(var i=0;iName是函数对象的一个属性。如果要在调试器中检查函数实例,您将在其上看到一个
Name
属性。对于在全局范围中定义的函数,
Name
的值将自动用作
窗口
引用它的对象


在内联函数的情况下,您正在定义函数将被引用的属性的名称。JS引擎不需要使用函数实例中的
name
属性。

“有人能解释一下为什么吗“如果你想问这个设计决策的原因,你应该联系在ECMAScript标准中工作的人。@FelixKling嗨,再见!你是从我的问题中抄袭评论吗?@FelixKling,这不是关于设计决策:)我只是想了解这个概念在内部是如何工作的,不是为什么ECMA中有人喜欢这个概念;)@tkoomzaaskz:在这种情况下,您可以在规范中找到技术解释:。它明确地说:“可以从
FunctionExpression
FunctionBody
内部引用
函数表达式中的
标识符
,以允许函数递归调用自身。但是,与
函数声明
不同,
函数表达式
中的
标识符
不能从中引用,并且不会影响包含
函数表达式
的范围。“我正在努力理解你的解释。我知道,当控件进入javascript中的一个新函数时,会创建新的作用域上下文,并将新的变量对象附加到它——这很清楚。现在你写道:当你使用var ninja时,你现在处理的是ninja作用域-你的意思是当我声明一个新变量(在本例中,变量引用一个函数)时,变量有一个新的作用域(不是函数)?
var ninja;
// myNinja; - what would you expect it to be here?
for (var i=0; i<5; i++)
    ninja = function myNinja(){
        console.log(myNinja);
    };
// myNinja; - *which one* would you expect it to be here?
ninja();