当前位置

网站首页> 程序设计 > 开源项目 > 程序开发 > 浏览文章

JS预编译 - 小土豆

作者:小梦 来源: 网络 时间: 2024-07-16 阅读:
if ("a" in window) {    var a = 1;}alert(a);

先来看这个题会alert出什么呢?答案很显然会是:1

不过这道题目放在以前考我的话,那我一定会答错,后来查找了一番资料,了解到两个新名词:预编译变量提升,为了以后不会忘记,还是留个笔记吧。

首先来了解一下什么是预编译:对var关键字先提前声明(值先设为undefined,执行时才给实际值),接着对函数定义式进行提前加在var后头,再接着顺序执行代码,函数定义式在预编译时期就被解析,执行时期仍然用这个值,而无论是声明的变量还是声明式函数,在执行的时候,可以覆盖预编译时期的值。

下面我们来解释一下上面的题目为什么是1呢,首先上面的代码等价于下面的代码:

var a;if("a" in window){    a = 1;}

因为js没有块级作用域,所以if里面的也是全局的,所以在预编译过程中里面的变量a会被提出来并被赋值为undefined,然后在执行if语句时候此时a已经存在于window中了,只不过值暂时是undefined,于是就会去执行if里面的代码,所以结果为1;

再来一题:

var a = 1;function a(x){}alert(a);等价于:var a;a = function(x){}a = 1;alert(a);

预编译阶段寻找代码中的var(实际将var a=1拆分为var a;a=1两部分,第一部分置顶,第二部分挂在语法树上)以及function两个关键字并置顶,在此将a以及a()分别置顶,之后在执行阶段再对a从语法树进行赋值,最后a为1。

理解了上面的代码,下面再看一个类似的题目:

function a(x) {    return x ;}var a;alert(a);等价于:var a;function a(x){    return x;}alert(a);

这个题目跟上一个有点类似,但是却又不同,原因就是在这里a并没有被赋值,而只是声明一个变量;在预编译阶段会将这种形式提前置顶,然后将function也置顶,但是function在a之后,于是预编译后二者顺序完全倒过来了,所以最后执行结果是function a(x){return x;}。

如果显式的给a赋值一个a=undefined;那么结果就是undefined。因为此时牵扯到赋值了 赋值的话 就在执行阶段去执行。

     Fn();  //执行结果:"执行了函数2",同名函数后者会覆盖前者     function Fn(){ //函数1        alert("执行了函数1");     }      function Fn(){  //函数2        alert("执行了函数2");     }
      Fn();  //执行结果:"执行了声明式函数",在预编译期声明函数及被处理了,所以即使Fn()调用函数放在声明函数前也能执行。      function Fn(){ //声明式函数         alert("执行了声明式函数");      }       var Fn = function(){  //赋值式函数         alert("执行了赋值式函数");      }

通过对比上面两段代码,我们不难发现,声明式函数与赋值式函数的区别在于:在JS的预编译期,声明式函数将会先被提取出来,然后才按顺序执行js代码,所以才有这样的结果。

热点阅读

网友最爱