Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/sorting/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
函数级作用域的优缺点(特别是在Javascript中)_Javascript - Fatal编程技术网

函数级作用域的优缺点(特别是在Javascript中)

函数级作用域的优缺点(特别是在Javascript中),javascript,Javascript,与Java等语言中的块级范围相比,Javascript中的函数级范围有哪些优点和缺点 我希望看到一些函数级作用域使用的示例,这些示例使用块级作用域将更难或不可能实现。首先想到的示例是:如果使用块级作用域实现,JavaScript处理函数级作用域的成本将高得多 当您在JavaScript中输入一个函数时,会分配一个对象(好吧,一对,但我们将重点关注一个),该对象最终成为“变量对象”——也就是说,该函数调用的所有参数和局部变量都保存在该对象中(作为属性)。闭包实际使用的是这个对象(不仅仅是它似乎使用

与Java等语言中的块级范围相比,Javascript中的函数级范围有哪些优点和缺点


我希望看到一些函数级作用域使用的示例,这些示例使用块级作用域将更难或不可能实现。

首先想到的示例是:如果使用块级作用域实现,JavaScript处理函数级作用域的成本将高得多

当您在JavaScript中输入一个函数时,会分配一个对象(好吧,一对,但我们将重点关注一个),该对象最终成为“变量对象”——也就是说,该函数调用的所有参数和局部变量都保存在该对象中(作为属性)。闭包实际使用的是这个对象(不仅仅是它似乎使用的“符号”;这是一个常见的误解)。这些对象串在一个称为作用域链的链中,用于解析非限定符号


想象一下,如果每个块都引入了新的作用域,那么成本会高出多少。

没有什么你做不到的——用块级作用域模拟函数级作用域并不难,反之亦然

但是,条件函数声明会更加笨拙:

if (console && console.log) {
    function debug(msg) { console.log(msg); }
} else {
    function debug(msg) { alert(msg); }
}
debug('foo'); // does not work with block scope
我想看看函数级作用域使用的例子,使用块级作用域更难或不可能实现

也许这听起来很明显,但您可以在函数级范围内实现递归,这通常很有用,例如:

var x = 5; // global scope

(function (y) { // y - locally scoped variable on each execution
  y && arguments.callee(--y); // recursion!
  console.log(y);
})(x);
这在块级范围内几乎不可能实现

在上面的示例中,函数将首先执行,并将外部
x
变量的值传递给它,在调用函数之前,将设置一个新的执行上下文,该上下文初始化一个新的词法范围,其中
y
形式参数绑定到它


之后,再次执行函数表达式-如果
y
不是
0
-每次执行时初始化一个全新的词法作用域。

您的意思是如果使用块级作用域实现。@Peter:Crikey,现在手指滑倒了。。。谢谢这实际上从未被标准化过,它只在Mozilla实现中起作用,因为它们定义了一个函数语句,这在ECMAScript规范中是不存在的。其他实现将只接受最后一个
FunctionDeclaration
,尽管该代码应该导致一个
SyntaxError
,因为没有语法产品可以接受块内的FD。@CMS:确实如此。Tgr:应该使用函数表达式有条件地分配函数。请参阅@CMS:“…因为没有语法产品可以接受FD的内部块。”哇,这部分我不知道。我知道
FunctionDeclaration
将被处理,不管它在函数中的什么位置(例如,不是有条件的),但我没有意识到语法不支持它。正如你所指出的,这当然是个坏主意。正如Marcel所说,使用函数表达式(正如Marcel在kangax的文章中指出的,除非你愿意,否则使用匿名表达式)。@T.J.,是的,大量实现支持一些非官方的语法扩展,另一个例子是文本:
08
09
,它们是无效的
NumericLiteral
,因为
DecimalIntegerLiteral
不能以
0
开头(当然,除非
0
值本身),并且它们与
OctalIntegerLiteral
语法:
0 OctalDigit
不匹配,因为显然,一个八进制数字只能是
0
中的一个,
1
2
3
4
5
6
7
。这些文本应该导致一个
语法错误
,但在所有实现中,前导零都被忽略,
08==8
09==9