Javascript 为什么在';如果';条件';外部不可见的表达式部分?
为什么日志会导致错误,Javascript 为什么在';如果';条件';外部不可见的表达式部分?,javascript,Javascript,为什么日志会导致错误,f尚未在上述表达式中定义 您可能认为这相当于: if (function f() {}) { console.log(f) // Throw an error: f is not defined } 函数声明被视为函数表达式(如函数(){}),而不是函数语句 证明: if (function f() {}) { console.log(f) // Throw an error: f is not defined } 如果函数实际上是一条语句,则无法立即
f
尚未在上述表达式中定义
您可能认为这相当于:
if (function f() {}) {
console.log(f) // Throw an error: f is not defined
}
函数声明被视为函数表达式(如函数(){}),而不是函数语句
证明:
if (function f() {}) {
console.log(f) // Throw an error: f is not defined
}
如果函数实际上是一条语句,则无法立即执行它(如果不将其括在括号中或在其前面加上!
将其转换为表达式)
你的假设是错误的。这两个片段并不相同。第一种是不存储值(实际的函数对象)的。这样的对象总是真实的-因此执行
if
get
这些函数的函数名(或者更确切地说应该是)仅在函数本身内部可见(某些早期IE版本除外)。因此,由于
f
根本不存在,当您试图将其传递到控制台时,会抛出ReferenceError
。log
函数声明语句在其周围范围内定义函数,甚至将定义移到顶部。但是,这是一个命名函数表达式。函数由其内部的名称定义,而不是外部的名称(旧IE中除外,它是一个bug)。除此之外,它只是一个设置了名称的函数。只有当语句以关键字function
开头时,它才算作function语句
这项工作:
function f(x) {return x}(false) //Would yield a syntax error
当你说
function f(){};
if (f) console.log(f);
它是一个函数声明语句。此函数将在封闭环境中定义。因此,如果它是在另一个函数中定义的,那么该函数将在该环境中定义,您可以通过名称访问该函数
但是,当您在表达式中使用函数声明时,它将不会被视为函数声明,而是函数表达式,其计算方式如下(引用自)
生产
函数表达式:
function f () {}
评估结果如下:
true
作为Strict标志传入由程序在当前环境上下文中将函数对象指定给变量以保留函数。否则,当表达式计算完成时,新创建的环境上下文将无效。因此,函数
f
在外部将不可见。我不确定为什么要在if
语句中声明一个函数,如果您在它上面声明var f=function(){}
,它就可以正常工作。此外,如果执行if(f=function(){})
它工作得很好。块范围和函数范围之间似乎存在混淆,但我认为这与此无关。我建议编辑。@Doge,你的编辑把问题弄糊涂了。您正在将变量f声明为函数。这与声明函数不同。正如许多人所说,如果(f=function(){})
有效。。。因为它将函数存储在一个全局变量中。function f(){}
相当于var f=function(){}
假定了某些约束。您认为原始代码等同于什么?条件现在为false,因此不会打印任何内容。这并不能解释为什么if
语句中没有f
。这是一个激进的编辑。是其他答案之一改变了你的想法吗?:-)不,我只是想弄清这个问题的真相,仅此而已。所以我检查了规格。@mpm:Excellent插图,当涉及到b/w语句和表达式的差异时。然而,在我的例子中,最后一行没有产生语法错误(Google Chrome)。你的解释和链接在我看来很好地解释了这个问题。我甚至试过,因为这个问题本身非常有趣。-“factorial”名称仅在函数体中可见。很可能f
是一个引用错误,而且console.log
甚至没有被调用;当然,console.log
可以记录未定义的
为什么它的行为像一个命名函数?我认为命名函数应该像本例中的@Smeegs那样被赋值。放置(如if条件)使其成为表达式而不是声明。命名函数表达式中的名称不是来自变量名,而是来自函数名。这在函数本身之外是不可见的。明白了,这就是为什么函数从未声明过。它计算函数声明,但实际上并不声明函数(函数本身之外)
function f(){};
if (f) console.log(f);
function f () {}
function Identifier ( FormalParameterListopt ) { FunctionBody }