javascript - 为什么变量声明不允许作为参数,而函数声明可以?

标签 javascript

这可能是个愚蠢的问题。我用谷歌搜索但找不到答案。如下所示,变量声明不允许作为函数的参数。

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

作用域存在于更大的作用域中。内部作用域可以访问周围的作用域(因此 ab 在 block 内部可见)但反之则不行(因此 b 在外部不可见)。

当您创建 function 时调用中的对象...

f(function a() { })

...它们被困在内部范围内,无法从外部引用。

4。赋值是表达式

在您的示例代码中,您注意到声明 a像这样工作:

f(a = 5)

这……很不幸。确实是 Javascript 历史的产物。在现代代码中,您应该始终使用 letconst定义变量。

那么它为什么有效?两个原因。首先,因为它是一个赋值,而不是一个声明。像这样:

let x = 1
f(x = 2)

赋值是表达式。他们评估分配的值。 x = 2 的值是2 , 和 x作为副作用发生变化。

5.有一个全局范围

第二个原因是不幸的。当你避开 let , varconst关键字,您隐式使用了 global范围。

这是所有作用域之母,可以从代码中的任何位置访问存在于其中的名称。所以,如果你只是这样做......

f(a = 5)

... 没有声明 a当前作用域中的任何地方,它在全局作用域中隐式声明,并且赋值发生。把它想象成这样(伪代码):

global let a
f(a = 5)

那当然不是有效的 Javascript。但是你明白了。

关于javascript - 为什么变量声明不允许作为参数,而函数声明可以?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54032324/

相关文章:

javascript - jquery 验证消息未显示

javascript - 尽管设置了@match 和@include 设置,Chrome 用户脚本仍会在所有页面上触发

javascript - 如何使用 jQuery 检查元素是否可见?

javascript - jQuery:如何使用文字对象方法中的方法获取全局变量

javascript - RxJS +(异步/等待)用于(多事件)用例

javascript - 当条件为真时保持选项禁用

javascript - 重新初始化 javascript 对象的属性

javascript - html4 中的自定义键盘 Tab 键顺序

javascript - 如何将单个状态 Prop 重置为其初始值

javascript - 如何替换/替换字符串内的数字作为字符串内字母的乘数?