详解函数和变量的声明提升 - 蓝蓝设计_UI设计公司

帝皇彩票官网

追求卓越一诺千金

蓝蓝设计,2011年成立,主创清华团队,专注软件和互联网ui设计开发。擅长企业信息化管理、监控、大数据软件UIUE咨询和设计开发服务。立足UI,好好学习,天天进步!


详解函数和变量的声明提升

2019-11-22 释然 前端及开发文章及欣赏


详细解读—函数和变量的声明提升
一 - 声明提升常见面试题
☛我们先以几道面试题开头来引入,
☛大家可以先给自己做出一个答案,然后再看文章的思路捋一捋哟。

来一道基础的吧~

var a="Hello";  
function test(){  
  alert(a); 
  var a="World";
  alert(a);
}
test();

难度+1

var a = 1;
function outer(){ 
  a = 2; 
  function inner(){       
      alert(a); 
      a = 4; 
  } 
  inner();

outer(); 
alert(a);

继续加油

(function(){
  f1(); 
  f2();
  var f1 = function(){};
  function f2(){
      alert(1);
  }
})();

最后一道

(function () {
   console.log(a);
   var a=1;
   function a() {
       console.log("biu~");
   }
})()

二 - 究竟什么是声明提升?
引擎在解释JS代码之前,首先要对JS代码进行编译,其中编译的一部分工作就是找到所有的声明,包括变量和函数的所有声明都会在任何代码被执行前首先被处理。
var a = 1这句话会被浏览器读成 var a和a = 1两句话执行,其中var a会在编译阶段就先执行了,而a = 1这段赋值代码会在原地等待执行阶段。
console.log(a); 
var a = 2;

上边这段代码,如果代码按照顺序由上自下执行,那么执行到console.log(a);时,a还没有声明,所以会包一个找不到变量a的错,但是事实上,这句话打印了一个undefined,说明a被声明了,但是没有被赋值,那么结合上一段的文字,我们可以得出代码实际运行的是这样的:

var a;
console.log(a);
a = 2;

三 - 函数的提升
大家可能在书写代码的时候发现,无论函数封装写在前或者后,我们的函数调用都可以顺利执行。

fn1();//可以执行
function fn1() {
    console.log("hello");
}

为什么呢?其实函数声明,包括函数的代码块都i会被提升,所以调用函数的时候,函数声明已经被执行过了。

但是有个案例大家了解一下:

fn2();//报错,fn2不是一个函数
var fn2 = function () {
   console.log("world");
}

我们可以看到 以给匿名函数赋值的形式定义函数,只会提升函数声明,但是函数表达式却不会被提升。因为变量fn2被提升,但是并没有赋值,我们书写的fn2()无法运行,而抛出了异常。
以下就是实际执行的顺序:

var fn2;
fn2();
fn2 = function () {
   console.log("world")
}

函数优先提升
我们都知道了,函数声明和变量声明都会被提升,那么遇到这样的情况会怎么办?

fn3();
var fn3=function () {
    console.log("fn3-1");
}
fn3();
function fn3() {
    console.log("fn3-2");
}

哎呦,嘛情况,突然迷了!!!
☛ 这个时候你就要考虑,同样的一个变量名称,到底是把var fn3给先提声上去,再提升 fn3函数体?还是先提升 fn3函数体,再提升var fn3???其实都不对!!!

☛ 答案是:函数会被优先提升,但后才是变量提升,但是当函数提升后,然后发现还有一个变量声明和函数声明一样的名称,这个就是重复声明,那么这个var fn3 是不生效直接忽略的。

所以实际代码运行顺序是:

function fn3() {
   console.log("fn3-2");
}
fn3();//fn3-2
fn3=function () {//var fn3因为重复声明被忽略
   console.log("fn3-1");
}
fn3();//fn3-1

当然,我们还是建议再同一个作用域重复声明是很烂的选择

说在最后
再代码作用域中的声明,都会在代码执行前被首先处理,所有的声明都会被移动到各自作用域的最顶端,这个过程就叫做声明提升。

四 - 答案:
问题1:

var a="Hello";  
function test(){  
  alert(a); 
  var a="World";
  alert(a);
}
test();

实际执行:
var a="Hello";
function test(){
   //作用域有声明a,声明提升到这里
   var a;
   alert(a);//本作用域声明a,所以不去使用父作用域的a,但是本作用域的a没有赋值,所以弹出undefined
   a="World";
   alert(a);//赋值后 ,弹出world
}
test();

问题2:

var a = 1;
function outer(){ 
  a = 2; 
  function inner(){       
      alert(a); 
      a = 4; 
  } 
  inner();

outer(); 
alert(a);

执行结果:

var a = 1;
function outer(){
   a = 2;
   function inner(){
       //本作用域没有声明a,所以没有任何提升,直接执行
       alert(a); // 所以弹出 a为 2
       a = 4;
   }
   inner();
}
outer();
alert(a);//只有全局声明了a,所以所有作用域使用的都是全局的a,所以a最后被赋值为4 弹出4

问题3

(function(){
  f1(); 
  f2();
  var f1 = function(){};
  function f2(){
      alert(1);
  }
})();
实际执行结果:

(function(){
   function f2(){
       alert(1);
   }
   var fn1;
   f1();//提升后先执行fn1(),但是fn1被提升的是变量不是函数,所以这里报错,不是一个函数
   f2();//上一句话报错,这句话不再运行
   f1 = function(){};
})();

问题4:

(function () {
   console.log(a);
   var a=1;
   function a() {
       console.log("biu~");
   }
})()
实际执行结果:

(function () {
   function a() {
       console.log("biu~");
   }
   console.log(a);//打印了a这个函数的函数体
   a=1;//因为函数有限声明提升,所以这里的var a被提升时,发现重复声明,故被忽略了var a;    
})()

标签: 详解函数和变量的声明提升 « 2020年UI界面设计趋势 | 认知与UI设计»


蓝蓝 http://www.bjhbys.com

  1. 2020年2月(6)
  2. 2020年1月(32)
  3. 2019年12月(50)
  4. 2019年11月(61)
  5. 2019年10月(49)
  6. 2019年9月(48)
  7. 2019年8月(58)
  8. 2019年7月(58)
  9. 2019年6月(58)
  10. 2019年5月(31)
  11. 2019年4月(37)
  12. 2019年3月(43)
  13. 2019年2月(25)
  14. 2019年1月(45)
  15. 2018年12月(41)
  16. 2018年11月(40)
  17. 帝皇彩票官网2018年10月(29)
  18. 2018年9月(40)
  19. 2018年8月(87)
  20. 2018年7月(107)
  21. 2018年6月(86)
  22. 2018年5月(110)
  23. 2018年4月(40)
  24. 帝皇彩票官网2018年3月(35)
  25. 2017年8月(35)
  26. 2017年7月(45)
  27. 2017年6月(7)
  28. 2017年5月(27)
  29. 帝皇彩票官网2017年4月(51)
  30. 帝皇彩票官网2017年3月(70)
  31. 2017年2月(65)
  32. 帝皇彩票官网2017年1月(69)
  33. 2016年12月(55)
  34. 2016年11月(111)
  35. 2016年10月(92)
  36. 2016年9月(53)
  37. 2016年8月(9)
  38. 2016年7月(4)
  39. 2016年6月(9)
  40. 2016年3月(19)
  41. 2016年2月(26)
  42. 2016年1月(30)
  43. 2015年12月(33)
  44. 2015年11月(35)
  45. 2015年10月(46)
  46. 2015年9月(43)
  47. 2015年8月(40)
  48. 2015年7月(33)
  49. 2015年6月(46)
  50. 2015年5月(58)
  51. 2015年4月(70)
  52. 2015年3月(55)
  53. 2015年2月(17)
  54. 2015年1月(33)
  55. 2014年12月(21)
  56. 2014年11月(84)
  57. 帝皇彩票官网2014年10月(94)
  58. 2014年9月(6)
  59. 2014年8月(1)
  60. 2014年7月(13)
  61. 2014年6月(66)
  62. 2014年5月(99)
  63. 2014年4月(88)
  64. 2014年3月(102)
  65. 2014年2月(68)
  66. 2014年1月(83)
  67. 2013年12月(106)
  68. 2013年11月(112)
  69. 2013年10月(61)
  70. 帝皇彩票官网2013年9月(20)
  71. 2013年7月(13)
  72. 2013年6月(27)
  73. 2013年5月(48)
  74. 2013年4月(39)
  75. 2013年3月(8)
  76. 2013年2月(20)
  77. 2013年1月(31)
  78. 2012年12月(33)
  79. 2012年11月(31)
  80. 2012年10月(23)
  81. 2012年9月(8)
  82. 2012年7月(14)
  83. 2012年6月(15)
  84. 2012年5月(31)
  85. 2012年4月(24)
  86. 2012年2月(4)
  87. 2012年1月(8)
  88. 2011年12月(35)
  89. 2011年11月(32)
  90. 2011年10月(13)
  91. 2011年8月(1)
  92. 2011年6月(1)
订阅Rss
吉利彩票开奖 快3平台 大象彩票APP 博发彩票开奖 桔子彩票开奖 贵州快3走势 河北快3开奖 状元彩票开奖 吉林快3走势 568彩票计划群