变量提升和函数提升 与预解析

201 阅读4分钟

预解析

预解析(pre-parsing)是指浏览器在执行HTML文档的解析和渲染之前,对文档进行初步解析的过程。预解析可以提高网页加载速度和资源利用效率

预解析过程包括以下几个步骤:

  1. 提前加载外部资源:浏览器会提前发起外部资源(如CSS、JavaScript等)的请求,并在下载完成后直接缓存,以减少后续页面加载时的延迟。
  2. 构建文档树:浏览器会将HTML文档转换成DOM树,并识别出所有的标签和元素节点。
  3. 构建样式规则树:浏览器会将CSS样式表转换成CSS规则树,并匹配出所有与文档元素相关的样式规则。
  4. 创建布局树:浏览器会将DOM树和CSS规则树合并成一棵布局树,并确定每个元素的几何位置和大小等布局属性。
  5. 执行预解析脚本:浏览器会执行在文档中定义的所有JavaScript脚本,对元素进行修改和操作。
  6. 渲染页面:最后,浏览器会将布局树中所有元素的视觉表示绘制在屏幕上,完成页面的渲染。
    JavaScript代码的预解析
    JavaScript代码执行由浏览器JavaScript解析器来执行,JavaScript解析器执行JavaScript代码时,分为:预解析过程代码执行过程两个部分
    预解析:
    1. 把变量的声明提升到当前作用域的最前面,注意:只提升声明,不提升赋值,(可以理解为声明了一个变量,但是没有赋值)
    2. 把函数声明提升到当前作用域的最前面,注意:只提升声明,不提升调用
    3. (优先级)先提升函数声明,后提升变量声明

变量提升

变量的声明提升到当前作用域的最前面,注意:只提升声明,不提升赋值,(可以理解为声明了一个变量,但是没有赋值)

        var num=88
        function fn(){
            console.log(a)//undefined
            var a=99
        }
        fn()

执行结果

image.png 变量提升的理解:在变量声明前,可以访问变量,只是不能访问变量的值

 //////////////////fn() 代码执行时候,可以理解为
        function fn(){
             var a //把var a=99 声明的a 提升到了当前fn()函数作用域的最前面,但是只提升了var a   没有赋值
              console.log(a)
              var a=99

            }

函数提升

函数声明提升到当前作用域的最前面,注意:只提升声明,不提升调用

        //声明之前访问
        console.log(fn1)//undefined 
        var fn1=function(){
            console.log('123456')
        }
        
        //声明之后访问
        console.log(fn1)
    </script>

执行结果

image.png 函数提升的理解:在函数声明的前面,可以访问这个函数,只是访问不到里面的内容

可能有的小伙伴存在疑惑,难道得到undefined,就是变量提升和函数提升?
首先理解一下,undefined:声明了变量,但是没有赋值
再看一下,没有声明的变量直接访问是什么样的

image.png 没有声明就直接访问的变量,浏览器胡抛出一个错误error,如图,Uncaught ReferenceError: a is not defined(a这个变量没有被定义)
所以,undefined在此章--变量提升中表示的是,在声明之前访问了变量,变量声明提升到了当前作用域最前面,浏览器访问到了变量,只是因为没有提升赋值,所以返回给我们一个undefined

# 函数表达式不存在提升

函数表达式不具有函数提升是因为它的定义方式是通过赋值给变量或对象属性来完成,而不是通过函数声明的方式在作用域中创建一个标识符。这意味着在JavaScript引擎预解析代码时,并不会将使用函数表达式定义的函数提前到当前作用域的顶部。

例如:

sayHello(); // 抛出 "Uncaught TypeError: sayHello is not a    function" 错误
 var sayHello = function() {
  console.log("Hello!");
}

在该例中,尝试在函数表达式之前调用 sayHello() 函数会抛出类型错误,因为变量 sayHello 存在于作用域中,但尚未被赋值。与此相对应的,函数声明则允许在当前作用域内任何位置都能被调用。
==================>
===>注意使用 var 关键字定义的变量,被称为变量声明;


==>let/const声明的变量会有暂时性死区,声明之前不能调用.