如果在牛客网刷题的小伙伴,你会发现很多代码执行的结果和你预想的不一致,首先看下面的一段代码

var a=10;
(function test(){
console.log(a)
var a=15;
console.log(a)
})();

上面一段代码,之前一直以为结果是10,15 实际执行结果为

undefined
15

看到结果很意外,问什么第一次打印结果为undefined,这里就要讲到变量提升,任何函数内部变量都会先提升,你可以理解为执行顺序为:

var a=10;
(function test(){
var a;
console.log(a)
a=15;
console.log(a)
})();

看到这个执行顺序是不是感觉很清晰了,变量提升之后,作用域发生了改变,下面我们就来讲讲作用域和变量提升

作用域:

javascript 在es6之前的版本只有全局作用域和函数作用域

全局作用域:在函数任何位置都能访问到,生命周期伴随着页面的生命周期,

函数作用域:是指在函数内部定义的变量和函数,只能在函数内部访问,函数执行之后,函数内部的变量和函数都会被销毁。

es6之后才引入块作用域同时利用let、const来处理var缺陷(变量提升)

一、变量提升:

如果变量声明在函数里面,则将变量声明提升到函数的开头;

如果变量声明是一个全局变量,则将变量声明提升到全局作用域的开头;

变量提升分为两步,第一步变量声明的提升,第二步变量的赋值;

案例1:全局变量提升

console.log(a); // 'undefined'
var a = 'csdn';
console.log(a); // csdn

实际运行时代码:

var a;  // 全局变量声明提升
console.log(a); // 'undefined'
a = 'csdn';
console.log(a); // csdn

 案例2:函数内变量提升

var a = 'global';
function fun() {console.log(a); // 'undefined'var a = 'local';console.log(a); // local
}
fun();
实际运行时代码:
var a ; // 全局变量声明提升a ='global';//声明后赋值
function fun() {var a; //函数内变量声明提升console.log(a); // 'undefined'a = 'local';//函数内赋值console.log(a); // local
}
fun();

 二、函数提升

函数的提升是直接将整个函数整体提升到作用域的最开始位置,相当于直接复制到开始;

函数声明只会提升函数声明,不提升函数表达式;

函数提升后会生成一个函数表达式;

案例1:函数声明式

console.log(fun1); // [Function: fun1]
fun1(); // fun1
function fun1() {console.log('fun1');
}
实际运行时代码
var fun1=function(){
console.log('fun1');
}
console.log(fun1); // [Function: fun1]
fun1(); // fun1
案例2:函数表达式,保持原来不变
console.log(fun2); // undefined
fun2(); // TypeError: fun2 is not a function
var fun2 = function () {console.log('fun2');
};
实际运行时代码:
console.log(fun2); // undefined
fun2(); // TypeError: fun2 is not a function
var fun2 = function () {console.log('fun2');
};

三、提升顺序

函数声明提升比变量提升优先级要高,且不会被变量声明覆盖,但会被变量赋值时覆盖;

a() > a

案例:

console.log(a); // f a() {console.log(10)}
console.log(a()); //  undefined
var a = 3;
function a() {console.log(10); //10
}
console.log(a); //3
a = 6;
console.log(a()); //a is not a function;

实际执行结果

var a = function(){  // 函数提升
console.log(10);
}
var a;   // 变量提升
console.log(a); // f a() {console.log(10)}
console.log(a()); //  undefined
a = 3;
console.log(a); //3
a = 6;
console.log(a()); //a is not a function;

变量提升的意义

我们知道在js运行时需要分两步,一步是解析阶段,一步是执行阶段;

1、容错性更好:

 JS作为一个脚本语言,在代码解析阶段,对js进行预编译,就可以发现一些语法上的错误,及时抛出错误,容错性更好;

2、提高性能:

在解析阶段函数的语法检查与预编译,操作只执行一次,目的是为了提升性能,若没有语法解析和预编译,那每次代码执行都要进行预编译和为函数分配空间,这样将要浪费很多时间,占用很多空间,这就是为什么javascript运行速度很快,而Java执行速度很慢,因为每次运行的时候要先预编译。

块级作用域:var缺陷以及为什么要引入let和const | 浏览器工作原理与实践

Javascipt变量提升、作用域相关推荐

  1. JavaScript:变量提升作用域

    作用域是JavaScript中听上去感觉很简单,其实比较麻烦的一个特性,什么是作用域?我看书籍有一个相对的官方解释:作用域(scope,或译有效范围)就是变量和函数的可访问范围,即作用域控制着变量和函 ...

  2. JS 作用域与变量提升---JS 学习笔记(三)

    你知道下面的JavaScript代码执行时会输出什么吗? var foo = 1; function bar() {if (!foo) {var foo = 10;}console.log(foo); ...

  3. js变量作用域和变量提升

    在javascript中, 理解变量的作用域以及变量提升是非常有必要的.这个看起来是否很简单,但其实并不是你想的那样,还要一些重要的细节你需要理解. 变量作用域 "一个变量的作用域表示这个变 ...

  4. javascript --- js中的作用域 变量提升

    1 求以下函数的输出 1.1 考察点: 变量提升.this.作用域 // 考察点 作用域.this.变量提升 var a = 10 function test() {a = 100console.lo ...

  5. js变量提升_学习笔记:JS中的作用域和预解析

    知识总结:谢静贤.汤昊 在javascript中作用域是非常重要的,本文将会说明作用域以及我们在工作,以及面试中的一些面试题,如果有不足的地方希望大家可以评论指出来,自己一定会及时的改正错误,避免大家 ...

  6. 详解var、let、const关键词声明变量的区别,以及变量提升、块级作用域的认识等。

    首先回顾一下JavaScript中var声明变量的基础知识: • 在使用var关键词声明变量时,变量在函数外则是全局变量,有全局作用域,全局变量在页面关闭后销毁:变量在函数内则是局部变量,作用局部作用 ...

  7. 作用域、变量提升、函数提升、数据类型

    一.作用域分类 (作用域范围内定义的变量,整个作用域都可以访问) 1. 全局作用域 使用var声明(或者不严格模式下没有声明)且在函数外定义的变量,其作用域范围是全局的,称其为全局作用域. 2. 函数 ...

  8. 关于JavaScript的词法作用域及变量提升的个人理解

    关于JavaScript的作用域,最近听到一个名词:"词法作用域":以前没有听说过(读书少),记录一下对此的理解,加深印象. 词法作用域:在JavaScript中,一个函数的作用域 ...

  9. var/let/const、块级作用域、TDZ、变量提升

    概览 ES6 新增了两个定义变量的关键字:let 与 const,它们几乎取代了 ES5 定义变量的方式:var.let是新的var,const简单的常量声明. function f() {{let ...

最新文章

  1. 有原型的对象和没有原型的对象
  2. 某程序员吐槽自己追求某字节HR,暧昧半年,见面后却被告知是普通朋友!心态已崩!网友:别追HR!道行太深!...
  3. Linux C 中连接操作符##
  4. 哈·曼丁的故事(三)
  5. org.apache.hadoop.hive.metastore.api.SerDeInfo; local class incompatible
  6. SpringBoot与数据访问
  7. 【转】解决WCF大数据量传输 ,System.Net.Sockets.SocketException: 远程主机强迫关闭了一个现有的连接...
  8. java8新特性(3)--- 函数式接口
  9. (四)Linux内核模块化编程
  10. 28 PP配置-生产车间控制-工序-定义报工屏幕默认值
  11. [BZOJ1001]: [BeiJing2006]狼抓兔子
  12. android制作弹出框样式,Android Dialog 弹出框 自定义 样式
  13. linux常用ipc技术,LINUX系统编程之IPC
  14. 为什么K8s会成为主流?
  15. 项目:文本相似度分析(C++)
  16. 微信小程序中,数字等宽字体
  17. 联想全球裁员 MOTO移动业务被砍掉超过一半
  18. Windows7下安装sql2000个人版(可用,本人已测)
  19. STC12C5A60S2
  20. 陈小龙书pHP,PHP

热门文章

  1. 中文新闻分类 数据集_最新开源LiDAR数据集LSOOD:四种常见的室外物体分类
  2. Oracle:左连接、右连接、全外连接、(+)号详解
  3. c语言usleep头文件,C语言Sleep clock time函数的使用
  4. Android拍照及从相册选择图片传详解(终极版)
  5. 尴尬的央视大楼(大裤衩) --- 转载
  6. 自适应滤波-最小均方误差滤波
  7. webLogic漏洞目录
  8. VB这种语言现在还有什么用
  9. java断言--03--JUnit断言(Asserts)
  10. PCB对点之Mark点检测