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

时间:2018-10-24 07:50:36

标签: javascript function variables scope

  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不可更改,这是什么?

1 个答案:

答案 0 :(得分: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语句在外部范围中对声明为local的变量进行了更改,覆盖了声明为函数声明的副作用的旧的人工local。由于您使用的是非严格模式,因此很难看出其中的区别,但是,您可能会这样考虑实现:

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
}

这是一个实现细节。这里,声明函数的人工变量优先于声明的local。 a首次被声明为声明的变量,因此按原样计数。与人工变量相比,作为声明变量的问题使其可变。