Js代码分为两个阶段:编译阶段和执行阶段

Js代码的编译阶段会找到所有的声明,并用合适的作用域将它们关联起来,这是词法作用域的核心内容

包括变量声明(var a)和函数声明(function a(){})在内的所有声明都会在代码被执行前的编译阶段首先被处理

过程就好像变量声明和函数声明从他们代码中出现的位置被移动到执行环境的顶部,这个过程就叫做提升

只有声明操作会被提升,赋值和逻辑操作会被留在原地等待执行

变量声明

Js编译器会把变量声明看成两个部分分别是声明操作(var a)和赋值操作(a=2)

声明操作在编译阶段进行,声明操作会被提升到执行环境的顶部,值是undefined(表示未初始化)

赋值操作会被留在原地等待执行阶段

  1. var a = 2;
  2.  
  3. function foo() {
  4. console.log(a); //undefined
  5. var a = 10;
  6. console.log(a); //
  7. }
  8.  
  9. foo();
  10.  
  11. // 相当于
  12.  
  13. var a = 2;
  14.  
  15. function foo() {
  16. var a;
  17. console.log(a); //undefined
  18. a = 10;
  19. console.log(a); //
  20. }
  21.  
  22. foo();

函数声明

定义函数有两种方式:函数声明和函数表达式

函数声明提升会在编译阶段把声明和函数体整体都提前到执行环境顶部,所以我们可以在函数声明之前调用这个函数

函数表达式,其实就是变量声明的一种,声明操作会被提升到执行环境顶部,并赋值undefined。赋值操作被留在原地等到执行。

  1. // 函数声明
  2.  
  3. foo(); //
  4.  
  5. function foo(){
  6. console.log(100);
  7. }
  1. // 函数表达式
  2. baz(); // TypeError: baz is not a function
  3.  
  4. var baz = function(){
  5. console.log(200);
  6. }
  7.  
  8. //相当于
  9.  
  10. var baz;
  11.  
  12. baz();
  13.  
  14. baz = function() {
  15. console.log(200);
  16. };

控制语句

Js中使用函数级作用域,不存在块级作用域。所有普通块中的声明都会被提升到顶部,所以控制语句对声明的控制就显得完全没有效果

  1. if (false) {
  2. var a = 10;
  3. }
  4.  
  5. console.log(a); //undefined
  6.  
  7. // 相当于
  8.  
  9. var a;
  10. if (false) {
  11. a = 10;
  12. }
  13.  
  14. console.log(a) //undefined

奇怪的函数声明

  1. console.log(a); //undefined
  2.  
  3. if (false) {
  4. function a() {
  5. console.log(100);
  6. }
  7. }
  8.  
  9. a(); //TypeError: a is not a function 理论上应该是100

奇怪吧??函数提升发生在所有代码执行之前,所以尽管a函数的定义过程写在了if分支中,但是理论上,它是不会影响函数声明提升的

在新版本的浏览器中会出现此问题,旧版本的浏览器中会在控制台中打印出100

这也提醒了我们尽量不要在控制语句中进行声明,会造成很多无法预知的bug

函数优先

提升操作会优先进行函数的声明

函数会首先被提升然后才是变量,重复的变量声明会被忽略,只剩下赋值操作,多个函数声明可以进行覆盖

声明的顺序是这样的:

1. 找到所有的函数声明,初始化函数体,如有同名的函数则会进行覆盖

2. 查找变量声明,初始化为undefined,如果已经存在同名的变量,就什么也不做直接略过

  1. //
  2. foo(); //
  3.  
  4. function foo() {
  5. console.log(100);
  6. }
  7.  
  8. function foo() {
  9. console.log(200);
  10. }
  11.  
  12. //
  13. console.log(foo); //function foo(){...}
  14.  
  15. function foo(){
  16. console.log(200);
  17. }
  18. var foo = 100;

Js 变量声明提升和函数声明提升的更多相关文章

  1. 原型模式故事链(4)--JS执行上下文、变量提升、函数声明

    上一章:JS的数据类型 传送门:https://segmentfault.com/a/11... 好!话不多少,我们就开始吧.对变量提升和函数声明的理解,能让你更清楚容易的理解,为什么你的程序报错了~ ...

  2. JS 函数提升&变量提升以及函数声明&函数表达式的区别

    感谢原文作者:迟早会有猫 原文链接:https://www.cnblogs.com/SidselLoong/p/10515809.html 今天看js的变量提升问题,里面提到了函数提升.然后发现自己之 ...

  3. 【JS】函数提升变量提升以及函数声明和函数表达式的区别

    今天看js的变量提升问题,里面提到了函数提升.然后发现自己之前一直把函数声明和函数表达式弄错,导致函数提升出错 一.变量提升 console.log(a) var a=100 //undefined ...

  4. 【JS点滴】声明提前,变量声明提前,函数声明提前,声明提前的先后顺序

    声明提前,函数声明提前,好吧,老生常谈的问题了.正好,前些天在掘金看到一道关于声明提前的笔试题,那么这里就以这道题来作为本文的引子吧,代码如下: console.log(a)//? a();//? ; ...

  5. js变量的作用域、变量的提升、函数的提升

    变量的作用域在函数之外声明的变量,叫做全局变量,因为它可被当前文档中的任何其他代码所访问.在函数内部声明的变量,叫做局部变量,因为它只能在当前函数的内部访问. ECMAScript 6 之前的 Jav ...

  6. js中变量提升(一个是变量,一个是函数表达式都会存在变量提升,函数声明不存在)

    一.变量提升 在ES6之前,JavaScript没有块级作用域(一对花括号{}即为一个块级作用域),只有全局作用域和函数作用域.变量提升即将变量声明提升到它所在作用域的最开始的部分.上个简历的例子如: ...

  7. JS变量声明提升和函数声明提升

    JS代码在执行的时候会先找出执行代码中定义的变量和函数,对其进行声明. 例1:console.log(a); var a = 4; 此时输出undefined.a变量在执行console.log(a) ...

  8. 变量声明提升 Vs. 函数声明提升

    1. 变量声明提升 先看以下代码: 1)var in_window = "a" in window; console.log(in_window); 2)var in_window ...

  9. javascript变量声明提升和函数声明提升

    在ES6之前,JavaScript没有块级作用域(一对花括号{}即为一个块级作用域),只有全局作用域和函数作用域.变量提升即将变量声明提升到它所在作用域的最开始的部分. JS的解析过程分为两个阶段:预 ...

随机推荐

  1. Java多线程基础学习(二)

    9. 线程安全/共享变量——同步 当多个线程用到同一个变量时,在修改值时存在同时修改的可能性,而此时该变量只能被赋值一次.这就会导致出现“线程安全”问题,这个被多个线程共用的变量称之为“共享变量”. ...

  2. Android指纹解锁

    Android6.0及以上系统支持指纹识别解锁功能:项目中用到,特此抽离出来,备忘. 功能是这样的:在用户将app切换到后台运行(超过一定的时长,比方说30秒),再进入程序中的时候就会弹出指纹识别的界 ...

  3. android自定义控件一站式入门

    自定义控件 Android系统提供了一系列UI相关的类来帮助我们构造app的界面,以及完成交互的处理. 一般的,所有可以在窗口中被展示的UI对象类型,最终都是继承自View的类,这包括展示最终内容的非 ...

  4. Python标准库--typing

    作者:zhbzz2007 出处:http://www.cnblogs.com/zhbzz2007 欢迎转载,也请保留这段声明.谢谢! 1 模块简介 Python 3.5 增加了一个有意思的库--typ ...

  5. 旺财速啃H5框架之Bootstrap(二)

    突然感觉不知道写啥子,脑子里面没水了,可能是因为今晚要出去浪,哈哈~~~提前提醒大家平安夜要回家哦,圣诞节生00000000000这么多蛋....继续 上一篇的已经把bootstrap了解个大概了,接 ...

  6. Tesseract-OCR字符识别简介

    OCR(Optical Character Recognition):光学字符识别,是指对图片文件中的文字进行分析识别,获取的过程.Tesseract:开源的OCR识别引擎,初期Tesseract引擎 ...

  7. BPM配置故事之案例5-必填与水印文本

    物资申请表改好了,但是没过两天老李又找来了. 老李:这个表格每次都是各个部门发给我们,再由我们采购部来填,太影响效率了,以后要让他们自己填. 小明:那就让他们填呗,他们有权限啊. 老李:可是他们说不会 ...

  8. .net core和angular2之前端篇—1

    2016-10-20更新 今天的这篇文章还是一篇"Hello World",只不过开发环境有所改变--Visual Studio Code+Angular2+Webapck,也算是 ...

  9. MySQL:Fabric 安装

    MySQL Fabric安装 MySQL Fabric是Oracle提供的用于辅助进行ha\sharding的工具,它的基本架构: 从上面看出,借助于Fabric, 可以搭建 HA 集群.Sharin ...

  10. 【腾讯Bugly干货分享】H5 视频直播那些事

    本文来自于腾讯bugly开发者社区,非经作者同意,请勿转载,原文地址:http://dev.qq.com/topic/57a42ee6503dfcb22007ede8 Dev Club 是一个交流移动 ...