JavaScript 变量提升

JavaScript 中,函数及变量的声明都将被提升到函数的最顶部。

JavaScript 中,变量可以在使用后声明,也就是变量可以先使用再声明。

这几天在刷题的过程中经常碰到关于变量提升作用域的问题。

作用域问题,在之前的博客有写过:Mr.J--JS学习(闭包私有化)

通常JS引擎会在正式执行之前先进行一次预编译,在这个过程中,首先将变量声明及函数声明提升至当前作用域的顶端,然后进行接下来的处理。(注:当前流行的JS引擎大都对源码进行了编译,由于引擎的不同,编译形式也会有所差异,我们这里说的预编译和提升其实是抽象出来的、易于理解的概念)。

var val = 12;
function foo(){console.log(val);var val = 20;console.log(val);
}
foo();

我刚开始看这段代码,以为是作用域的问题,然后认为输出是: 12 20;

但是这段代码通过变量提升,可以转化成以下的代码:

var val = 12;
function foo(){var val;console.log(val);var val = 20;console.log(val);
}
foo();

答案很明显了:undefined 20

变量提升:函数声明和变量声明总是会被解释器悄悄地被"提升"到方法体的最顶部。

JavaScript 初始化不会提升

var x = 5; // 初始化 xelem = document.getElementById("demo"); // 查找元素
elem.innerHTML = x + " " + y;           // 显示 x 和 yvar y = 7; // 初始化 y

在这段代码中,在使用y的值之后出现了y值的初始化,转化代码格式:

var x = 5; // 初始化 x
var y;     // 声明 yelem = document.getElementById("demo"); // 查找元素
elem.innerHTML = x + " " + y;           // 显示 x 和 yy = 7;    // 设置 y 为 7

最终输出:x 为:5,y 为:undefined

函数提升

function bar() {foo(); // output: I am hoistedfunction foo() {console.log('I am hoisted');}
}bar();

为什么函数可以在声明之前就可以调用,并且跟变量声明不同的是,它还能得到正确的结果,其实引擎是把函数声明整个地提升到了当前作用域的顶部,预编译之后的代码逻辑如下:

// 预编译之后
function bar() {function foo() {console.log('I am hoisted');}foo(); // output: I am hoisted
}bar();

其实这个就是执行上下文的有关问题了。好多学习JavaScript的人一般不会注意变量提升的问题,这样就会导致代码极其容易出错。

之前写过相关的博客,博客链接:一篇文章让你理解面试难点:执行上下文(干货满满(附面试题))

同样,如果出现同名函数,将会进行函数的覆盖,即后者覆盖前者:

function bar() {function foo() {console.log(1);}foo(); // output: 2function foo() {console.log(2);}
}bar();

为什么要进行提升

由于第一代JS虚拟机中的抽象纰漏导致的,编译器将变量放到了栈槽内并编入索引,然后在(当前作用域的)入口处将变量名绑定到了栈槽内的变量。(注:这里提到的抽象是计算机术语,是对内部发生的更加复杂的事情的一种简化。)

然后,Dmitry Soshnikov又提到了函数提升,他提到了相互递归(就是A函数内会调用到B函数,而B函数也会调用到A函数)。函数提升就是为了解决相互递归的问题,大体上可以解决像ML语言这样自下而上的顺序问题。

总结

function jsFun6(){  //函数声明和函数表达式的区别test1();//函数声明提升,在执行代码之前会先读取函数声明,不会报错function test1(){//函数声明方式创建函数alert("测试1");}//test2();报错,函数还不存在console.log(test2)//不会报错,变量提升只是提升变量的声明,并不会把赋值也提升上来,输出undefinedvar test2=function(){alert("测试2");};//使用函数表达式创建一个匿名函数(实际是以变量test3命名的函数)test2();//不会报错,以创建函数var test3=function(){alert("测试3");}();//加了括号立即执行var test4 = 12;// !注意看,一旦变量被赋值后,将会输出变量//函数提升优先级高于变量提升,所以函数先提升,然后变量提升覆盖之前的函数声明,表                //现为变量function test4() {alert("测试4");               }console.log(test4); //12var test5="test5_1";(function(){//js中的变量搜索顺序:找变量时,先找局部变量,如果没有局部变量;再找全局变量。alert(test5);//此时的test5为局部变量的提升,undefinedvar test5="test5_2";})();}

只要理解了执行上下文,对于变量提升就会一下看懂。一篇文章让你理解面试难点:执行上下文(干货满满(附面试题))

JavaScript 变量提升相关推荐

  1. JavaScript变量提升

    JavaScript变量提升 在JavaScript中变量声明与函数声明都会被提升到作用域顶部,优先级依次为: 函数声明 变量声明 变量赋值. 变量提升 var的变量提升 console.log(a) ...

  2. JavaScript变量提升机制

    JavaScript变量提升机制 Js代码执行前(栈内存)还做了一件事那就是变量提升,Js会在所有var function等关键字的提前声明或者定义.. 看以下的代码: console.log(a); ...

  3. php变量 声明提升,JavaScript 变量提升

    JavaScript 变量提升 JavaScript 中,函数及变量的声明都将被提升到函数的最顶部. JavaScript 中,变量可以在使用后声明,也就是变量可以先使用再声明. 以下两个实例将获得相 ...

  4. javascript变量提升/函数提升

    首先 javascript 是一种弱类型.动态的.解释型的脚本语言. 弱类型:类型检查不严格,偏向于容忍隐式类型转换. 强类型:类型检查严格,偏向于不容忍隐式类型转换. 动态类型:运行的时候执行类型检 ...

  5. JavaScript变量提升(Hoisting)详解

    文章出自个人博客https://knightyun.github.io/2019/09/02/js-hoisting,转载请申明. 概念 变量提升是 JavaScript 的一种执行机制,大致就是字面 ...

  6. Javascript变量提升与暂时性死区

    暂时性死区:在ES6之前,使用 typeof 运算符操作一个未声明的变量时,不会报错,该变量的值以 undefined 作处理.而在ES6之后,使用ES6的变量声明方法(let, const, cla ...

  7. javaScript变量提升以及函数提升

    变量的声明赋值 var a = 1; 上面的代码先声明变量 a,然后在变量 a 与数值 1 之间建立引用关系,称为将数值 1 "赋值"给变量 a.以后,引用变量名 a 就会得到数值 ...

  8. JavaScript 变量提升的作用

    文章目录 前言 预解析时期 正式执行时期 一.举例 1. 函数提升-求以下代码执行结果 2. 函数提升-求以下代码执行结果 3.函数提升-求以下代码的结果 4.变量提升-求以下代码的结果 5.clas ...

  9. JavaScript 变量提升(hoisting)

    借鉴了一下菜鸟教程官网的解说. JavaScript 中,(1)函数及变量的声明都将被提升到函数的最顶部:(2)变量可以在使用后再进行声明. 变量提升:解释器总是会悄悄地把函数声明和变量声明" ...

最新文章

  1. SQL Server 2008最直观的变化上(三)
  2. 关于ie中easyui form组件load事件无法多次加载数据
  3. 【数据库系统概论】考研第二部分重点分析【2.2】
  4. linux OOM-killer机制(杀掉进程,释放内存)
  5. 操作系统:第二章 进程管理1 - 进程、线程
  6. java清除浏览器记录_java – 如何在Selenium测试中清除浏览器缓存
  7. c++ 怎样连接两个链表_LeetCode | 链表的入口,一文帮你搞定“环形链表”(python版,最简单解析)...
  8. 在飞音G801上运行OpenWRT+Asterisk
  9. leetcode139 单词拆分
  10. 膨胀的木棍(信息学奥赛一本通-T1246)
  11. java的Random类
  12. ios中获取各种文件的目录路径方法
  13. mysql改变授权_mysql8使用grant授权修改
  14. C语言——蔡勒(Zeller)公式的使用
  15. 基于 Mybatis 和 Springboot 的后台管理系统 BootDo | 软件推介
  16. 中国联通开放号码标记一键查询与清除服务
  17. 华为HCNA之OSPF多区域配置实验
  18. 发射极正偏,集电极反偏
  19. 【论文阅读】Multi-Modal Sarcasm Detection 图文反讽识别
  20. 无线路由器的基础配置(一)

热门文章

  1. 58页PPT揭示图神经网络研究最新进展
  2. 0基础学Python,要报班吗?
  3. 顶尖!百度AI算法专家手把手带你论文复现打比赛!
  4. 最新!2020世界一流大学学术排名出炉!
  5. TensorFlow中查看checkpoint文件中的变量名和对应值
  6. 精选论文集:三维点云有哪些必读的论文?
  7. 数据结构期末复习之插入排序
  8. Tensorflow新手通过PlayGround可视化初识神经网络
  9. [转]如何处理机器学习中的不平衡类别
  10. 地理学中常见图的名称(或者分析)