JS进阶——变量和函数提升

变量提升

"变量提升"(Variable Hoisting)是JavaScript中的一个概念,它指的是在函数或代码块内部声明的变量(使用var关键字)在代码执行之前就被提升(hoisted)到其包含函数或全局作用域的顶部。这意味着你可以在声明之前的代码中访问这些变量,并且它们不会被认为是未定义的。

下面是一个关于变量提升的例子:

javascript 复制代码
function example() {  
    console.log(a); // 输出:undefined,而不是ReferenceError,因为变量a被提升了  
    var a = 5;  
    console.log(a); // 输出:5  
}  
  
example();

请注意,只有使用var声明的变量才会发生变量提升。使用letconst声明的变量(ES6中引入的块级作用域变量)不会经历变量提升,而是遵循所谓的"暂时性死区"(Temporal Dead Zone)规则,在声明之前的代码中访问它们会导致引用错误。

javascript 复制代码
console.log(a); 
var a = 5;  
//等同于

var a;
cosnole.log(a);
a=5

如果使用letconst来声明变量,情况就会不同:

javascript 复制代码
function example() {  
    console.log(a); // 抛出ReferenceError,因为变量a没有被提升  
    let a = 5;  
    console.log(a); // 这行代码不会执行到,因为前面的console.log已经抛出了错误  
}  
  
example();

函数提升

函数提升(Function Hoisting)是JavaScript中另一个与变量提升相关的概念。在JavaScript中,函数声明(function declarations)也会被提升到它们所在作用域的顶部。这意味着你可以在声明之前调用一个函数,并且它仍然可以正常工作。

javascript 复制代码
foo(); // 这将正常调用函数foo,即使它在下面才声明  
  
function foo() {  
    console.log("Hello, world!");  
}  
  
foo(); // 这也会输出"Hello, world!"

其实主要理解 js 的解析机制就行。

遇到 script 标签的话 js 就进行预解析,将变量 var 和 function 声明提升,但不会执行 function,然后就进入上下文执行,上下文执行还是执行预解析同样操作,直到没有 var 和 function,就开始执行上下文。如:

javascript 复制代码
a=5;
show();
var a;
function show(){};

预解析:

javascript 复制代码
function show(){};
var a;
a=5;
show();

需要注意都是函数声明提升直接把整个函数提到执行环境的最顶端。

注意

使用匿名函数的方式不存在函数提升,因为函数名称使用变量表示的,只存在变量提升。例:

javascript 复制代码
var getName=function(){
  console.log(2);
}

function getName(){
  console.log(1);
}

getName();
//结果为2

可能会有人觉得最后输出的结果是 1。但是 getName 是一个变量,因此这个变量的声明也将提升到顶部,而变量的赋值依然保留在原来的位置。需要注意的是,函数优先,虽然函数声明和变量声明都会被提升,但是函数会首先被提升,然后才是变量。

javascript 复制代码
//函数、变量声明提升后
function getName(){    //函数声明提升到顶部
  console.log(1);
}

var getName;    //变量声明提升
getName = function(){    //变量赋值依然保留在原来的位置
  console.log(2);
}

getName();    // 最终输出:2
javascript 复制代码
function jsFun6(){  //函数声明和函数表达式的区别
    
    test1();//函数声明提升,在执行代码之前会先读取函数声明,不会报错
    function test1(){//函数声明方式创建函数
        alert("测试1");
    }
    
    //test2();报错,函数还不存在
    console.log(test2)//不会报错,变量提升只是提升变量的声明,并不会把赋值也提升上来,输出undefined
    var test2=function(){
        alert("测试2");
    };//使用函数表达式创建一个匿名函数(实际是以变量test3命名的函数)
    test2();//不会报错,以创建函数
                
    var test3=function(){
        alert("测试3");
    }();//加了括号立即执行
    
    var test4 = 12;// !注意看,一旦变量被赋值后,将会输出变量
    //函数提升优先级高于变量提升,所以函数先提升,然后变量提升覆盖之前的函数声明,表                
    //现为变量
    function test4() {
        alert("测试4");               
    }
    console.log(test4); //12

    var test5="test5_1";
    (function(){
        //js中的变量搜索顺序:找变量时,先找局部变量,如果没有局部变量;再找全局变量。
    alert(test5);//此时的test5为局部变量的提升,undefined
    var test5="test5_2";
    })();
                
}

需要注意的是,函数提升和变量提升都只在同一个作用域内有效。在不同的作用域(比如嵌套函数内部)中,变量和函数提升的规则不会互相影响。

相关推荐
xing251626 分钟前
pytest-html
前端·html·pytest
茂茂在长安36 分钟前
Linux 命令大全完整版(11)
java·linux·运维·服务器·前端·centos
Violet51536 分钟前
ECMAScript规范解读——this的判定
javascript
知识分享小能手1 小时前
Html5学习教程,从入门到精通,HTML5 简介语法知识点及案例代码(1)
开发语言·前端·javascript·学习·前端框架·html·html5
IT、木易1 小时前
大白话React第二章深入理解阶段
前端·javascript·react.js
晚安7201 小时前
Ajax相关
前端·javascript·ajax
图书馆钉子户1 小时前
怎么使用ajax实现局部刷新
前端·ajax·okhttp
bin91532 小时前
DeepSeek 助力 Vue 开发:打造丝滑的单选按钮(Radio Button)
前端·javascript·vue.js·ecmascript·deepseek
qianmoQ2 小时前
第五章:工程化实践 - 第五节 - Tailwind CSS 常见问题解决方案
前端·css
那就可爱多一点点2 小时前
超高清大图渲染性能优化实战:从页面卡死到流畅加载
前端·javascript·性能优化