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";
    })();
                
}

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

相关推荐
m0_7482550215 分钟前
前端常用算法集合
前端·算法
真的很上进29 分钟前
如何借助 Babel+TS+ESLint 构建现代 JS 工程环境?
java·前端·javascript·css·react.js·vue·html
web1309332039835 分钟前
vue elementUI form组件动态添加el-form-item并且动态添加rules必填项校验方法
前端·vue.js·elementui
NiNg_1_2341 小时前
Echarts连接数据库,实时绘制图表详解
前端·数据库·echarts
如若1232 小时前
对文件内的文件名生成目录,方便查阅
java·前端·python
滚雪球~2 小时前
npm error code ETIMEDOUT
前端·npm·node.js
沙漏无语2 小时前
npm : 无法加载文件 D:\Nodejs\node_global\npm.ps1,因为在此系统上禁止运行脚本
前端·npm·node.js
supermapsupport2 小时前
iClient3D for Cesium在Vue中快速实现场景卷帘
前端·vue.js·3d·cesium·supermap
brrdg_sefg2 小时前
WEB 漏洞 - 文件包含漏洞深度解析
前端·网络·安全
胡西风_foxww3 小时前
【es6复习笔记】rest参数(7)
前端·笔记·es6·参数·rest