图解 Google V8
李兵
前盛大创新院高级研究员
26763 人已学习
新⼈⾸单¥59
登录后,你可以任选4讲全文学习
课程目录
已完结/共 25 讲
图解 Google V8
15
15
1.0x
00:00/00:00
登录|注册

04 | 函数表达式:涉及大量概念,函数表达式到底该怎么学?

经典面试题的讨论
函数表达式可以用于变量隔离和代码隐藏
V8在编译阶段对函数声明和函数表达式的处理方式不同
函数声明和函数表达式有本质上的差异
将函数表达式赋给一个变量时,存储的是执行后的结果
可以避免变量污染
使用圆括号将函数定义为函数表达式
函数表达式之前无法使用该函数
函数表达式不会在编译阶段被提升到作用域中
使用D8查看作用域的状态
变量提升将函数对象放入作用域中
在编译阶段将函数声明转换为内存中的函数对象
函数表达式在编译阶段不会被提升到作用域中
函数声明在编译阶段被提升到作用域中
函数声明和函数表达式有本质上的差异
被广泛应用在各个项目中
可用于实现代码隐藏和变量隔离
JavaScript中非常基础也非常重要
思考题
总结
立即调用的函数表达式(IIFE)
V8是如何处理函数表达式的
V8是如何处理函数声明的
函数声明与函数表达式的差异
函数表达式
JavaScript函数表达式学习

该思维导图由 AI 生成,仅供参考

你好,我是李兵。
前面几节我们聊了 V8 中的对象和函数,并介绍了函数为什么会被称为是一等公民,了解这些之后,我们就可以来学习函数表达式了。
函数表达式在 JavaScript 中非常基础也非常重要,使用函数表达式可以用来实现代码隐藏,还可以实现变量隔离,所以函数表达式被广泛地应用在各个项目中,了解函数表达式的底层工作机制,可以帮助我们更加深刻地理解项目。
但是,学好函数表达式并不容易。因为它涉及到了很多底层概念,比如表达式、语句、函数即对象(在 JavaScript 中)等,而且函数表达式和函数声明看起来类似,都是定义一个函数,然后再调用该函数,很容易把二者搞混淆了。
你知道两者的区别吗?
实际上,函数表达式和函数声明有着本质上的差异。理解了这种差异,你对函数表达式的理解也就加深了。

函数声明与函数表达式的差异

那么它们具体有什么差异呢?我们先来看一段代码:
foo()
function foo(){
console.log('foo')
}
在这段代码中,我声明了一个 foo 函数,然后在 foo 函数之前调用了 foo 函数,执行这段代码,我们看到 foo 函数被正确执行了。(你可能会好奇,代码不是自上而下执行吗,为什么在函数声明之前就可以调用该函数了呢?这个问题我们先留一边,后文中会进行解答。)
再来看另外一段代码:
确认放弃笔记?
放弃后所记笔记将不保留。
新功能上线,你的历史笔记已初始化为私密笔记,是否一键批量公开?
批量公开的笔记不会为你同步至部落
公开
同步至部落
取消
完成
0/2000
荧光笔
直线
曲线
笔记
复制
AI
  • 深入了解
  • 翻译
    • 英语
    • 中文简体
    • 中文繁体
    • 法语
    • 德语
    • 日语
    • 韩语
    • 俄语
    • 西班牙语
    • 阿拉伯语
  • 解释
  • 总结

JavaScript中的函数表达式是一项基础且重要的概念,它可以用于实现代码隐藏和变量隔离。本文通过比较函数声明和函数表达式的差异,深入探讨了V8引擎处理函数声明的过程。在V8执行JavaScript代码时,会先对其进行编译,然后再执行。在编译阶段,V8会将函数声明转换为内存中的函数对象,并将其放到作用域中,这一过程称为变量提升。相比之下,函数表达式具有不同的语义和行为。函数表达式在编译阶段并不会将函数对象提升到全局作用域中,因此无法在函数表达式之前使用该函数。此外,文章还介绍了立即调用的函数表达式(IIFE)的概念和应用。通过本文的解析,读者可以更深入地理解函数表达式的底层工作机制,从而更好地应用于实际项目中。文章还留下了一道经典面试题,引发读者思考和讨论。 总的来说,本文通过深入解析V8引擎处理函数表达式的过程,帮助读者更好地理解了函数声明和函数表达式之间的区别,以及立即调用的函数表达式的应用。文章内容丰富,涵盖了函数表达式的底层工作机制和实际应用,适合对JavaScript感兴趣的读者阅读学习。

仅可试看部分内容,如需阅读全部内容,请付费购买文章所属专栏
《图解 Google V8》
新⼈⾸单¥59
立即购买
登录 后留言

全部留言(38)

  • 最新
  • 精选
  • 白闹
    老师,我有一个巨大的疑问,麻烦您有时间的话,一定帮我解答,回答是或不是就行! 在函数即对象一文,您提到“函数有个隐藏属性是 code 属性,其值表示函数代码,以字符串的形式存储在内存中。”,所以我理解成了,函数本质是储存在栈中的! 可是在这篇文里,你明确说到函数是被v8储存在堆中里的。 能解释下,具体是什么回事么? 因为感觉函数和普通对象还是有些区别的,之前看那篇文章里提到的code属性,以为区别就是函数有一部分是储存在栈中,现在似乎是我理解错了?请帮忙确认一下,谢谢老师!!

    作者回复: 抱歉,最近事情一堆,忙得不可开交,耽误回复问题了! 不知道我理解你的意思对不对,你的意思是无论什么原生类型都是存放在栈中的,比如某个对象中的一个属性值,如果它是个原生类型,那么原生该值会存放在栈中! 这个理解是错误的,如果你定义了一个对象,那么在运行时,改对象一定是存放在堆中的,包括对象里面的原生类型的属性值也是存放在堆中的! 所以当一个V8在编译阶段解析到一个函数声明时,它首先在堆中创建改函数对象,然后为改对象设置各个属性值! 还有问题欢迎继续提问🤗

    2020-04-10
    25
  • 在文中一会说 解析阶段,一会说编译阶段,这里这两个概念是一样的吧,解析阶段就是编制阶段,生成 作用域和字节码

    作者回复: 嗯 , 大的范围上来讲,我把从源码解析到输出字节码和字节码编译为二进制代码,都称为编译阶段,执行字节码和执行二进制代码称为执行阶段! 小范围来讲,编译阶段又分为解析,预解析、生成字节码、编译成二进制代码! 这里一个是大范围的编译,一个是小范围的! 写的时候也注意到这个问题了,但是没有想到一个更简洁的方式

    2020-03-24
    2
    18
  • Corryenjoy
    有一个疑问,以前看过一个篇阮一峰老师的关于loop event的文章。里面有一句话是这样的:“所有任务都在主线程上执行,形成一个执行栈。“ 按照当前文章的理解,所有的程序在执行前引擎都会有一个编译过程,生产作用域和字节码。这样在编译过程中,函数的执行应该会把所有的函数加入一个执行队列中,然后按照先进先出方式对函数进行执行。这样的理解对于在主线程的任务应该是一个执行队列,而不是一个执行栈。 所以想请老师帮忙解惑一下~

    作者回复: 消息队列里面的存放的是一个个嗷嗷待执行的任务,然后主线程会从消息队列中按照特定的策略: while(1){ 取出任务() 执行任务() } 在执行每个任务的过程中,都会有一个栈结构来管理这个任务的函数调用关系; 所以说,执行栈又称调用栈,它是针对消息队列中的单个任务的!

    2020-04-08
    14
  • 王楚然
    思考题: 1. 输出100,100。函数表达式立即执行,修改n值为100。 2.输出1,100。 函数只是被放入作用域,并未执行,因此n值先为1,调用函数后为100。

    作者回复: 没问题

    2020-03-24
    2
    10
  • qinsi
    文中提到IIFE的写法是 (function () { //statements })() 而第一题里是 (function () { //statements }()) 效果是一样的

    作者回复: 是的

    2020-03-24
    2
    6
  • 一飞同学
    从 V8 编译的角度理解变量提升,豁然开朗,比之前的理解清晰多了。

    作者回复: 赞

    2020-04-09
    2
  • 洋洋
    第一题输出: 100 100 第二题输出: 1 100

    作者回复: 没问题

    2020-03-24
    2
  • 杨越
    老师,函数立即表达式是一种特别的表达式,主要用来封装一些变量、函数,可以起到变量隔离和代码隐藏的作用。难道函数声明就不能封装变量和函数从而起到变量隔离和代码隐藏的作用了吗???再者,代码隐藏作何解???还望老师百忙中回复这两个问题

    作者回复: 因为当初JavaScript只有函数级作用域,没有块级作用域和空间作用域,所以要实现模块化开发,隐藏内部函数和变量只能使用函数,通常情况下,我们使用函数立即表达式,也就是将一个函数内部需要使用的方法和变量直接暴露给一个全局变量! 函数和函数立即表达式都能隐藏变量,但是通常模块化开发都是使用函数立即表达式来封装内部方法和变量,并直接返回需要暴露的内容!

    2020-03-24
    2
    1
  • 流乔
    老师说的编译一个版本的D8工具啥时候放出来呀?期待。辛苦老师😉😉😉

    作者回复: 下周

    2020-03-24
    1
  • 我想问下,文章在讲变量声明以及函数声明提升可以解释一些现象,其他脚本语言很少见到变量和函数提升,JS中它出现的背景是什么?是JS标准就这么规定死的?

    作者回复: 主要是JS当初的定位是一个非常简单的脚本语言,并没有想搞得太复杂了,不支持块级作用域,所以就搞了个变量提升的坑! 一直祸害至今,虽然目前已经支持块级别了作用域了,但是还要同时支持变量提升这个坑

    2020-03-24
    2
    1
收起评论
显示
设置
留言
38
收藏
沉浸
阅读
分享
手机端
快捷键
回顶部