这可能是个愚蠢的问题。我用谷歌搜索但找不到答案。如下所示,变量声明不允许作为函数的参数。
function t(a) {
alert(a);
}
t(var x = 1); // Uncaught SyntaxError: Unexpected token var
t(let x = 1); // Uncaught SyntaxError: missing ) after argument list
t(x = 1); // working fine and later I am able to access x also
console.log(x); // printing 1
但是函数声明被允许作为函数的参数,如下所示。
function callback(str, f1, f2) {
if(str == "")
f1();
else
f2();
};
callback("", function b1() { alert("empty") }, function b2() { alert("not empty") }); // working fine
b1(); // Throwing error Uncaught ReferenceError: b1 is not defined
谁能帮我理解一下
- 为什么变量声明不允许作为函数的参数 但允许函数声明作为参数?
- 为什么我们不能访问声明为函数的函数 函数调用之外的参数?
最佳答案
好问题!我会把它分成几部分。此处将有很多 Material 可供谷歌搜索,因为您的问题涉及多个深层次主题。
1。语句没有值(value)
声明是声明。它们没有值(value),因此不能作为参数。这段代码...
let a = 1
...没有值(value),意味着这些都不起作用:
doStuff(let a = 1)
let b = (let a = 1)
(let a = 1) + 5
名字a
, 或 a + 5
, 或 f(a)
是表达式,与语句不同,表达式具有值。但是a
的声明本身没有。
请注意,您对此的直觉并不荒谬:在其他语言中,let a = 1
是一个计算结果为 1
的表达式.不在 Javascript 中。
2。函数是对象
但是,function
关键字确实有值:Function
它定义的对象。与为方便起见的语言构造变量不同,Functions
是存在于运行程序中的实际对象。我们说函数是一等对象。
你可以做所有这些:
doStuff(function f() {})
let a = function f() {}
let b = (function f() {}) + 5 // the result of this is funny
回到你的例子,然后:
callback(
"", // a String object
function b1() { alert("empty") }, // a Function object
function b2() { alert("not empty") } // a Function object
);
类似这样:
function b1() { alert("empty") }
function b2() { alert("not empty") }
callback("", b1, b2)
但不完全是。让我们谈谈作用域。
3。名称在范围内定义
名称(例如变量或函数)的范围是具有该定义的代码部分。
例如:
// Top-level scope:
let a = 1
if (a == 1) {
// Inner block scope:
let b = 2
console.log(a, b) // 1, 2
}
console.log(a, b) // 1, undefined
作用域存在于更大的作用域中。内部作用域可以访问周围的作用域(因此 a
和 b
在 block 内部可见)但反之则不行(因此 b
在外部不可见)。
当您创建 function
时调用中的对象...
f(function a() { })
...它们被困在内部范围内,无法从外部引用。
4。赋值是表达式
在您的示例代码中,您注意到声明 a
像这样工作:
f(a = 5)
这……很不幸。确实是 Javascript 历史的产物。在现代代码中,您应该始终使用 let
或 const
定义变量。
那么它为什么有效?两个原因。首先,因为它是一个赋值,而不是一个声明。像这样:
let x = 1
f(x = 2)
赋值是表达式。他们评估分配的值。 x = 2
的值是2
, 和 x
作为副作用发生变化。
5.有一个全局范围
第二个原因是不幸的。当你避开 let
, var
或 const
关键字,您隐式使用了 global
范围。
这是所有作用域之母,可以从代码中的任何位置访问存在于其中的名称。所以,如果你只是这样做......
f(a = 5)
... 没有声明 a
当前作用域中的任何地方,它在全局作用域中隐式声明,并且赋值发生。把它想象成这样(伪代码):
global let a
f(a = 5)
那当然不是有效的 Javascript。但是你明白了。
关于javascript - 为什么变量声明不允许作为参数,而函数声明可以?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54032324/