函数提升的蜜汁行为

众所周知,JS里,变量有变量提升,函数有函数提升。ES6之前没有块级作用域。 然而,当用函数声明的方法定义function并遇到非ES6情况下的{}时,却有一些蜜汁行为。

一道题引发的惨案

if (true) {
      a = 1
      function a() {}
      // a = 1
      console.log(a)
    }
    console.log(a)
if (true) {
      // a = 1
      function a() {}
      a = 1
      console.log(a)
    }
    console.log(a)

理想状态下: if(){}里不存在letconst。应该不会产生Block块级作用域。 再根据函数提升,以上两者相当于

function a() {}
    a = 1
    console.log(a)
    console.log(a)

即输出11

实际情况却是: 前者11后者1f a(){}

调试分析

debugger调试分析问题 先将问题简化下

debugger
    console.log(a)
    if (true) {
      debugger
      function a() {}
      debugger
    }
    console.log(a)

输出undefinedf a(){}第一个debugger,js开始执行时,全局声明了a但未定义。

第二个debuggera的函数提升提升到块级作用域Block上,而非全局。

第三个debugger,此处才将Block内的a赋值给全局a

为什么是强调说是赋值而非直接在全局声明呢。 现在将a=1补上即再看一遍过程即可说明

debugger
    console.log(a)
    if (true) {
      debugger
      a = 1
      debugger
      function a() {}
      debugger
    }
    console.log(a)

第三个debuger时,1会覆盖掉Block里的f a(){}

第四个debuger时,执行到function的定义时,会发现全局a变成了1

最后这一步执行的前后,很明显可以看出,当执行当函数声明语句时,js会将块级里的函数名属性值赋给全局的函数名属性,即window.a = block.a。 实际执行情况约等于如下

var a;// 定义但未赋值,由function a(){}产生的。
    if (true) {
      let a = function a(){} // 函数提升到块级
      a = 1
      window.a = a // 声明语句时将块级a赋值给全局a
      console.log(a)
    }
    console.log(a)

个人理解总结

结论仅个人从结果推导,非查阅文档所得,所以未必准确。

(非es6情况下)当{}里存在函数声明(function a(){}这种类型)时,js执行情况如下:

  1. js开始执行,函数名全局声明但未定义
  2. 进入函数声明的{},产生临时Block,并且function函数提升到Block
  3. 直到执行该function的定义语句时,才会把Block里该函数名的属性赋值给全局(哪怕改变了该属性甚至类型),举例:window.a = a
原文链接:segmentfault.com

上一篇:【TS深深化史 -- 破晓】一步一个脚印带你入门 TS
下一篇:利用eventemitter2实现vue组件通信

相关推荐

  • 🔥0202年了,几个基础的手写函数总得会吧

    这几天看到一个大三大佬面试字节跳动的蚊子,突然觉得自己太辣鸡了···校招的题我一半多都不会啊···赶紧潜下心来学习学习提(an)高(wei)自己,边翻掘金边谷歌,简单实现了几个常用函数···(借鉴了太...

    2 个月前
  • 高阶函数的使用

    问题 字节跳动面试时问题:原函数例如fetchData是一个异步函数,尝试从服务器端获取一些信息并返回一个Promise。写一个新的函数可以自动重试一定次数,并且在使用上和原函数没有区别。

    1 年前
  • 高阶函数应用之柯里化与反柯里化

    背景 在 JavaScript 中,柯里化和反柯里化是高阶函数的一种应用,在这之前我们应该清楚什么是高阶函数,通俗的说,函数可以作为参数传递到函数中,这个作为参数的函数叫回调函数,而拥有这个参数的函数...

    5 个月前
  • 高阶函数应用 —— 柯里化与反柯里化

    在这里插入图片描述(https://img.javascriptcn.com/c94dd1ec0a5064d3cba1b5d9c7842670 "在这里插入图片描述") 前言 在 JavaScr...

    2 年前
  • 高阶函数&&高阶组件

    高阶函数 特点: 接受函数类型的参数。 返回值是函数。 高阶函数具有可扩展性。 常见的高阶函数: 定时器 setTimeout(); setInterval() Promise(); 数组相关:...

    3 个月前
  • 高质量的函数

    函数优化 我们上一章将了纯函数,这一章讲函数的优化 把一些强相关,定制型强的字段抽象出来,进行数据传递,里面所保存的为不相干变量。 我们也可以将函数作为参数进行传递 高阶函数 高...

    2 年前
  • 高级程序设计:第7章-函数表达式

    函数表达式是JavaScript中的一个既强大又容易令人困惑的特性。 定义函数表达式的方法 1.函数声明 先有function关键字,然后是函数的名字,就是指定函数名的方式。

    1 年前
  • 高级函数技巧-函数柯里化

    我们经常说在Javascript语言中,函数是“一等公民”,它们本质上是十分简单和过程化的。可以利用函数,进行一些简单的数据处理, 结果,或者有一些额外的功能,需要通过使用闭包来实现,最后经常会 匿名...

    1 年前
  • 高级JavaScript:为什么这个函数用圆括号封装?[重复]

    Peter Mortensennerdess(https://stackoverflow.com/users/63550/petermortensen)提出了一个问题:Advanced JavaScr...

    2 年前
  • 面试被问到Vue?想进一步提升?那就停下来看一下吧

    Vue作为最近最炙手可热的前端框架,其简单的入门方式和功能强大的API是其优点。而同时因为其API的多样性和丰富性,所以他的很多开发方式就和一切基于组件的React不同,如果没有对Vue的API(有一...

    9 个月前

官方社区

扫码加入 JavaScript 社区