分享web开发知识

注册/登录|最近发布|今日推荐

主页 IT知识网页技术软件开发前端开发代码编程运营维护技术分享教程案例
当前位置:首页 > 软件开发

JS执行顺序-函数声明提升、匿名函数、函数表达式

发布时间:2023-09-06 01:45责任编辑:顾先生关键词:匿名函数

大方向上: JS 是按照 代码块 进行 编译、执行 的。

学习至:

  • 1.变量声明提升
  • 2.新唐的博客
  • 3.js中匿名函数的创建与调用方法分析
  • 4.前端圣经 - 高程三
  • 5.深入理解变量声明提升和函数声明提升

因为没有好好地分类。可能会比较杂。为了系统地学习,先了解几个概念。

一. <script> 区分的代码块。

JS是按照代码块 编译 和 执行的。代码块间 相互独立,但是 变量和方法 共享。

<script> ?alert('代码块一');</script><script> ?alert('代码块二');</script>
<script> ?var a = 3;</script><script> ?console.log(a); // 3</script>

二. 关于函数(声明式函数、赋值型函数、匿名函数、自执行函数)

  • 声明式函数 和 赋值型函数

    声明函数与赋值函数的区别在于: 在 JS 的预编译期间,声明式函数会被先提取出来,然后才按照顺序执行 JS代码。

    声明式:

    A(); ?// 'A 'function A() { ?console.log('A');}

    赋值型:

    B(); // error, B is not a functionvar B = function() { ?console.log('B');}
  • 什么是匿名函数?

    没有名字的函数就是匿名函数。

    function() {} // 匿名函数
  • 什么是自执行函数

    (function() { ?console.log(3);})();

    需要注意,下面这样的写法会报错

    function() { ?console.log(3);}();
    原因解析如下:
    1. function {}()其实这是一个函数声明。
    2. JS运行的时候,会对函数声明进行预编译,然后在执行其他语句。
    3. 也就是说function(){}先被预编译了。然后JS看见了()。JS一脸懵逼,这不得报错吗。
    4. 而匿名函数实际上是一个语句,正常执行。

    还需要知道的是,自执行函数的标识可以是

    !function(){}() ?????????????(function(){})() ????~function(){}() ?????void function(){}()

    自执行函数是可以带参数的,格式是这样的!

    function(num){ ?console.log(num);}(3); ?????????????// 3

三. 预编译期 和 执行期

事实上,JS的解析分为两个阶段:预编译 和 执行期。

  • 预编译期间:对本代码块中的所有 声明变量 和 函数进行处理(类似于 C语言的编译) ,但需要注意,1.此时处理函数的只是 声明式函数2.变量也只是进行了声明但是没有进行初始化和赋值

  • 编译期间:从上到下 编译 代码块。

接下来,我们分别结合上面的 第一点(代码块) 和 第二点(函数) 食用一下。

f(); ?// 我是函数声明2function f() { ?console.log('我是函数声明1');}function f() { ?console.log('我是函数声明2');}

结论1:都是函数声明的情况下,后来居上的规则 没有变。

f(); ?// 我是函数声明function f() { ?console.log('我是函数声明');}var f = function() { ?console.log('我是赋值型函数');}

结论2:函数声明 提前于 赋值函数。

console.log(a);var a; // undefinedconsole.log(b); // 程序直接报错,不往下进行

函数下方声明了 a,被提前(提升)了。函数下方没有声明 b(之前也没有),直接报错。
结论3:变量声明 处于 预编译阶段。证明了我们上面的正确性。

<script> ?f();</script><script> ?function f(){};</script>

结论4:JS引擎是按照代码块的顺序来执行的。!!!对于还未加载的代码,是没有办法进行预处理的。这也是编译核心所在。

console.log(f); ?// Functionfunction f() { ?console.log(1);}var f = 3;

结论5:函数声明提升优先级大于 变量声明,函数声明覆盖 变量声明

<script> ?console.log(a);</script><script> ?console.log(3);</script>

结论6:代码块之间如果报错,其他的代码块如果正确依旧能够正确执行。


四. 开战!!! 五是总结和整理,不想看题目的可以直接跳至 五。


代码一:

f();var scope = 'out';function f() { ?console.log(scope); ?var scope = 'in'; ?console.log(scope);}
  • 变量覆盖,后面定义声明的会覆盖前面的。
  • 函数内部:先进行变量声明。

实际运行过程:

var scope = 'out';function f() { ?var scope; ???// 覆盖了外部的。 ?console.log(scope); ?scope = 'in'; ?console.log(scope);}f();

代码二:

var getName = function(){ ?console.log(2);}function getName (){ ?console.log(1);}getName();

这题看懂了前面的话很容易:

  • 函数声明被放在了预编译阶段。
  • 后来的会覆盖前面的。
    实际运行过程
function getName (){ ?console.log(1);}var getName = function(){ ?console.log(2);}getName(); ?// 2

代码三:

getName(); ????// 1function getName() { ?console.log(1);}var getName = function() { ?console.log(2);}

依旧很容易,不解释。变量赋值来得太慢,不像龙卷风。



五. 总结和整理

JS的执行顺序如下:

  • 1.读入第一个代码块
  • 2.做语法分析,有错则报语法错误,并跳转到 5
  • 3.对var变量和function做 预编译(永远不会报错,因为只解析正确的)
  • 4.执行代码块,有错则报错
  • 5.如果还有下一个代码块,则读入下一个代码端,重复 2
  • 6.结束

六. 想了想,是不是没有提到变量提升?这个其实是 JS的一个 乌龙。

ES之前,JS没有变量作用域。只有 函数作用域 和 全局作用域。

{ ?var a = 3;}console.log(a); // 3

使用了 ES6 的 let 之后, {} 内即为一个 变量作用域。

{ ?let a = 3;}console.log(a); // error

变量提升 完。

JS执行顺序-函数声明提升、匿名函数、函数表达式

原文地址:https://www.cnblogs.com/can-i-do/p/8574450.html

知识推荐

我的编程学习网——分享web前端后端开发技术知识。 垃圾信息处理邮箱 tousu563@163.com 网站地图
icp备案号 闽ICP备2023006418号-8 不良信息举报平台 互联网安全管理备案 Copyright 2023 www.wodecom.cn All Rights Reserved