FE-DSHUI / DSHUI

前端王者小分队读书会
4 stars 1 forks source link

《你不知道的JavaScript(上卷)》-函数声明提升-2021-1-22分享 #15

Open AwakenedSomeone opened 3 years ago

AwakenedSomeone commented 3 years ago

在js的编译过程中,存在变量提升和函数声明提升。这个概念我以前也知道,但是有些细节却不了解。

  1. 函数声明和变量声明都会被提升,但是函数会首先被提升,然后才是变量。如以下代码:
    foo();
    var foo;
    function foo() {
    console.log(1);
    }
    foo = function() {
    console.log(2)
    }

    上述代码打印的结果是1不是2,是因为第一个foo是函数声明,优先于第二个变量foo的声明,所以在编译的时候,遇到foo已经被声明了,再重复声明时,则会被忽略。 重要:重复的var 声明被会忽略掉,但是出现在后面的函数声明还是可以覆盖前面的。

  2. 函数声明可以提升,但是函数表达式不能提升。如:
    foo(); // 这里会报TypeError,而不是ReferenceError
    var foo = function bar () {
    // ...
    }

    这里报错的原因是: foo由var foo 声明了,并提升了,所以这个foo这个变量能通RHS查找到,但是值是undefined,因为 = function bar ...没有提升,此时调用foo则会报类型错误。

  3. 即使是具名的函数表达式,名称标识符在赋值之前也无法在所在作用域中使用:
    foo(); // 这里会报TypeError
    bar(); // 因为bar在函数表达式中,没有被提升,所以找不到bar,报错ReferenceError
    var foo = function bar () {
    // ...
    }

总结: 声明本身会被提升,但包括函数表达式的赋值在内的赋值操作不会被提升。

sworlife commented 3 years ago

第2点,没有看懂,不知道是在哪个位置调用 foo()

AwakenedSomeone commented 3 years ago

第2点,没有看懂,不知道是在哪个位置调用 foo()

写漏了,是在第一句前面调用,所以报错TypeError

isbaselvy commented 3 years ago

var foo; function foo() { console.log(1); } foo = function() { console.log(2) } 上述代码打印的结果是1不是2,是因为第一个foo是函数声明,优先于第二个变量foo的声明,所以在编译的时候,遇到foo已经被声明了,再重复声明时,则会被忽略

----这一点也没看懂,浏览器中输出是foo是第二个声明,调用foo()是打印的2 image