最通俗易懂的javascript变量提升详解


Posted in Javascript onAugust 05, 2017

如下所示:

a = 'ghostwu';
var a;
console.log( a );

在我没有讲什么是变量提升,以及变量提升的规则之前, 或者你没有学习过变量提升,如果按照现有的javascript理解, 对于上述的例子,你可能会认为第3行代码的输出结果应该是undefined, 因为第二行是var a; 声明变量,但是没有赋值,所以a的值是undefined, 但是正确的结果是ghostwu. 至于为什么,请继续往下看!

console.log( a );
var a = 'ghostwu';

对于上面这个例子,第一行代码,你可能认为报错, 因为在输出a之前,没有定义a变量, 但是正确的结果是undefined. 嗯,好像有点莫名奇妙,javascript太bug了.

要搞清楚为什么,首先我们要明确以下2点:

javascript代码并不是一行一行往下执行的.

javascript执行分为2个步骤:

编译(词法解释/预解释)

执行

其次,当我们碰到 var a = "ghostwu" 定义一个变量的时候, 其实js把这句话看成是2个阶段的事, var a 发生在编译阶段, a = 'ghostwu'发生在执行阶段. 然后 var a会被提升到当前作用域的最前面, a = 'ghostwu'留在原地等待执行阶段,所以:

a = 'ghostwu';
var a;
console.log( a );

//上面这段代码经过编译之后,变成下面这样

var a; //被提升到当前作用域的最前面
a = 'ghostwu'; //留在原地,等待执行
console.log( a );
console.log( a ); 
var a = 'ghostwu';

//上面这段代码,经过编译之后,变成下面这样

var a;
console.log( a );
a = 'ghostwu';

看完编译后的代码,你明白了吗?

在接着讲下面之前,我们先明确函数常见的2种定义方式:

//函数声明, 形如:
  function show(){
   console.log( '函数声明方式' );
  }

  //函数表达式, 形如:
  var show = function(){
   console.log( '表达式方式' );
  }

因为表达式和函数声明,在编译阶段,会产生不同的解释效果。

show();
  function show(){
   console.log( a );
   var a = 'ghostwu';
  }

对于上面这段代码,会在编译阶段,如何解释呢?记住下面这句话就行了:

函数声明会被提升

所以,上面的代码,经过编译之后,就变成了下面这样:

function show(){ //函数声明被提升到 当前作用域的最前面
   var a; //var声明被提升到当前作用域的最前面, 注意,他不会提升到函数的外面, 因为当前的作用域是在函数中
   console.log( a );
   a = 'ghostwu';
  }
  show();

所以,上面的结果就是undefined;

对于函数表达式,是不会提升的, 看下面的例子:

show(); //报错,show is not a function
var show = function(){
 console.log( 'ghostwu' );
}
//对于上面这段表达式代码,经过编译之后:
var show;
show(); //执行之后就是 undefined(), 所以在表达式定义之前,调用函数报错了
show = function(){
 console.log( 'ghostwu' ); 
}
show(); //你好
  var show;
  function show(){
   console.log( '你好' );
  }
  show = function(){
   console.log( 'hello' );
  }

上面这段代码,结果为什么会是 '你好'?

因为: 当出现同名的函数声明,变量声明的时候, 函数声明会被优先提升,变量声明会被忽略。 所以经过编译之后,就变成:

function show(){
   console.log( '你好' );
  }
  show(); //你好
  show = function(){
   console.log( 'hello' );
  }
  show();//如果这里在调用一次,就是hello, 因为show函数体在执行阶段 被 重新赋值了

如果有同名的函数声明,后面的会覆盖前面的,如下:

show(); //how are you
  var show;
  function show(){
   console.log( 'hello' );
  } 
  show = function(){
   console.log( '你好' );
  }
  function show(){
   console.log( 'how are you!' );
  }
//上面的代码经过编译之后,变成如下形式:
  function show(){
   console.log( 'how are you!' );
  }
  show(); //how are you
  show = function(){
   console.log( '你好' );
  }
  show(); //如果在这里再执行一次,结果:你好
//思考题: 请问下面的结果是什么? 为什么? 写下你的答案
   show();
   var a = true;
   if( a ){
    function show(){
     console.log( 1 );
    }
   }else {
    function show(){
     console.log( 2 );
   }
   }

以上这篇最通俗易懂的javascript变量提升详解就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
url 特殊字符 传递参数解决方法
Jan 01 Javascript
JQuery.closest(),parent(),parents()寻找父结点
Feb 17 Javascript
关于js new Date() 出现NaN 的分析
Oct 23 Javascript
web基于浏览器的本地存储方法应用
Nov 27 Javascript
JS给超链接加确认对话框的方法
Feb 24 Javascript
JQuery之proxy实现绑定代理方法
Aug 01 Javascript
js评分组件使用详解
Jun 06 Javascript
老生常谈js数据类型
Aug 03 Javascript
详解vue-router 路由元信息
Sep 13 Javascript
JavaScript运行原理分析
Feb 09 Javascript
webpack打包优化的几个方法总结
Feb 10 Javascript
Vue移动端项目实现使用手机预览调试操作
Jul 18 Javascript
Vue2.0 vue-source jsonp 跨域请求
Aug 04 #Javascript
js分页之前端代码实现和请求处理
Aug 04 #Javascript
微信小程序 rich-text的使用方法
Aug 04 #Javascript
Easyui和zTree两种方式分别实现树形下拉框
Aug 04 #Javascript
JS中使用media实现响应式布局
Aug 04 #Javascript
React Native第三方平台分享的实例(Android,IOS双平台)
Aug 04 #Javascript
node中Express 动态设置端口的方法
Aug 04 #Javascript
You might like
介绍几个array库的新函数 php
2006/12/29 PHP
PHP 程序授权验证开发思路
2009/07/09 PHP
PHP实现的微信APP支付功能示例【基于TP5框架】
2019/09/16 PHP
laravel 出现command not found问题的解决方案
2019/10/23 PHP
javascript编程起步(第一课)
2007/01/10 Javascript
js实现运行代码需要刷新的解决方法
2007/08/18 Javascript
ExtJs 表单提交登陆实现代码
2010/08/19 Javascript
在VS2008中使用jQuery智能感应的方法
2010/12/30 Javascript
NodeJS学习笔记之Connect中间件模块(一)
2015/01/27 NodeJs
JavaScript中连接操作Oracle数据库实例
2015/04/02 Javascript
JS简单限制textarea内输入字符数量的方法
2015/10/14 Javascript
整理Javascript基础入门学习笔记
2015/11/29 Javascript
轻松学习Javascript闭包函数
2015/12/15 Javascript
JavaScript实现阿拉伯数字和中文数字互相转换
2016/06/12 Javascript
JS函数修改html的元素内容,及修改属性内容的方法
2016/10/28 Javascript
vue使用vuex实现首页导航切换不同路由的方法
2019/05/08 Javascript
[01:19:34]2014 DOTA2国际邀请赛中国区预选赛 New Element VS Dream time
2014/05/22 DOTA
[01:34]2014DOTA2 TI预选赛预选赛 选手比赛房大揭秘!
2014/05/20 DOTA
[02:37]2015国际邀请赛选手档案—LGD.Xiao8
2015/07/28 DOTA
浅谈pytorch和Numpy的区别以及相互转换方法
2018/07/26 Python
python编程使用协程并发的优缺点
2018/09/20 Python
scrapy-redis的安装部署步骤讲解
2019/02/27 Python
详解django+django-celery+celery的整合实战
2019/03/19 Python
Python3+Pycharm+PyQt5环境搭建步骤图文详解
2019/05/29 Python
python 获取等间隔的数组实例
2019/07/04 Python
Python Django2.0集成Celery4.1教程
2019/11/19 Python
如何使用python实现模拟鼠标点击
2020/01/06 Python
Python自定义聚合函数merge与transform区别详解
2020/05/26 Python
Python常用数字处理基本操作汇总
2020/09/10 Python
详解用python -m http.server搭一个简易的本地局域网
2020/09/24 Python
阿拉伯世界最大的电子卖场:Souq埃及
2016/08/01 全球购物
美国照明、家居装饰和家具购物网站:Bellacor
2017/09/20 全球购物
社区党员先进事迹
2014/01/22 职场文书
《绿色蝈蝈》教学反思
2014/03/02 职场文书
党员一句话承诺大全
2014/03/28 职场文书
求职信结尾怎么写
2014/05/26 职场文书