一个命名函数表达式和一个函数声明有什么区别?

4
  1. var a = function b() {
        b = 123;
        console.log(b === window.a)  // true
        console.log(b)    // function b() { ... }
    }
  2. function a() {
       a = 3;
       console.log(a)    // 3
    }

为什么变量b不可更改,它是什么?


有趣的是,在函数内部,函数名绑定是不可重新赋值的。如果你使用了use strict,会得到Uncaught TypeError: Assignment to constant variable.(但这与const不同)。 - CertainPerformance
我更关心函数名b在内存中的形式。 - keyao Hou
1
您的标题中有一个问题,在帖子正文中有两个问题,在您的评论中又有一个问题。所有这些问题都已经在某个地方得到了回答。如果您将问题分成单独的帖子,将有助于您获得更多有用的答案(或重复关闭投票)。 - GOTO 0
1个回答

2
在Javascript中有两种类型的本地变量。它们是:
- 声明本地变量:当您使用关键字之一(例如varconstlet)声明本地变量时,这些变量被确定为已声明。在非严格模式下,您的变量声明会回退到var。 - 人工本地变量:当您使用函数声明语法声明函数时,实际上声明了一个名为函数名称的人工本地变量。例如,function foo() {}定义了一个名为foo的人工本地变量。
JavaScript根据变量提升在处理这两种类型的本地变量时有所不同。需要到达声明(或其第一次使用)才能引用已声明的本地变量。另一方面,人工本地变量会被提升到初始作用域状态,因此可以从作用域的开头使用。
您可以考虑以下代码:
bar();      // prints 'bar' on the console
foo();      // error: 'undefined' is not callable

const foo = function () {
  console.log('foo');
}

function bar() {
  console.log('bar')
}

bar();      // prints 'bar' on the console
foo();      // prints 'foo' on the console

在你的例子中,你的a = 3语句改变了在外部作用域中声明的局部变量,覆盖了你旧的人工局部变量,这个局部变量是由函数声明的副作用声明的。由于你使用的是非严格模式,很难看出区别,然而,你可以这样考虑你的实现:

var a_dec = function b_art () {
  b_dec = 123;
  console.log(b_art === window.a_dec);
  console.log(b_art);
}

function a_art () {
  a_dec = 3;
  console.log(a_dec);

  // when you run this, b_art is not reachable with a_dec anymore
}

这是一个实现细节。在此,声明函数的人工变量优先于已声明的本地变量。 a 首次被声明为已声明变量,因此它被视为它本身。成为已声明变量的问题使它可变,与人工变量相反。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接