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

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

相关推荐
Martin -Tang17 分钟前
vite和webpack的区别
前端·webpack·node.js·vite
迷途小码农零零发17 分钟前
解锁微前端的优秀库
前端
王解1 小时前
webpack loader全解析,从入门到精通(10)
前端·webpack·node.js
老码沉思录1 小时前
写给初学者的React Native 全栈开发实战班
javascript·react native·react.js
我不当帕鲁谁当帕鲁1 小时前
arcgis for js实现FeatureLayer图层弹窗展示所有field字段
前端·javascript·arcgis
那一抹阳光多灿烂1 小时前
工程化实战内功修炼测试题
前端·javascript
放逐者-保持本心,方可放逐2 小时前
微信小程序=》基础=》常见问题=》性能总结
前端·微信小程序·小程序·前端框架
毋若成4 小时前
前端三大组件之CSS,三大选择器,游戏网页仿写
前端·css
红中马喽4 小时前
JS学习日记(webAPI—DOM)
开发语言·前端·javascript·笔记·vscode·学习
Black蜡笔小新5 小时前
网页直播/点播播放器EasyPlayer.js播放器OffscreenCanvas这个特性是否需要特殊的环境和硬件支持
前端·javascript·html