JS预解析笔记

 

要明白JS预解析的运作方式,可以简单理解成两点:将声明语句提前执行,包括变量声明、函数声明、函数参数。其中函...



要明白JS预解析的运作方式,可以简单理解成两点:

  1. 将声明语句提前执行,包括变量声明、函数声明、函数参数。其中函数参数就相当于函数内局部变量声明
  2. 重新回到开始逐行解读代码,顺序是:从左到右、从上到下。
例子1:


alert(a);

alert(fn);

var a = 1;

function fn(){

return false;

}

/*

预解析过程:

1. 变量与函数提至作用域前面,变量赋值”未命名“,函数依旧是其完整函数块

2. 逐行解读代码,读到alert(a);时,返回检查此前提前的”var a “的值,验证为undefined,则alert(a)弹出undefined。alert(fn)同理。

var a = undefined;

function fn(){

return false;

}

alert(a);  //undefined

alert(fn);    //fn函数整个代码块

*/
//示例 1 解释

var a;              //  a 变量 提前到整个作用域的前面 当前值 为 undefind。

function fn(){

return false;
};                  //  fn 函数 提前整个作用域的前面 当前值 就是整个函数块。

alert(a);           //  undefind。
alert(fn);          //  function 整个函数块。

a=1;                //  a 赋值 1 现在 a  变量才拥有 值:1

function fn(){

return false;

};                  //  函数一直没变,只不过被提前到作用域的前面去了。

//  需要注意的是函数在那定义不重要,重要的是在那调用。

// (因为定义完以后它都会被提前到当前作用域的前面,所以函数在哪调用就在哪个作用域生效)


再来个例子2:


alert(a);

var a = 1;

alert(a);

function a(){

return false;

}

/*

首先还是两步走,变量与函数提前,

var a = undefined;

function a(){

return false;

}

这里就要注意,是不是发现函数名和之前的变量名重名了?这咋办?

根据JS解析器的规矩,后出来的同名函数会覆盖先出来的同名变量,

所以此时提到作用域(全局变量)前面的,只有函数名为a的函数块。

接下来就是逐行解读代码了,先是第7行alert(a)了,结果就弹出个a函数块来。

下面又要注意了,此时代码解析到第8行var a=1; 这明显又要走一波预解析提前的套路啊,此时a被赋值1。果然是三十年河东三十年河西,这下轮到a=1来覆盖原先的a函数块了。

所以第9行的alert(a)就弹出值 1。

下面第10行的函数块由于没有执行口子,所以代码执行就到此为止了。

*/
示例2:解释

var a;                  // 首先提前 变量 当前值 为:undefind。

function a(){

return false;
};                      // 遇到函数 提前函数 注意:当前函数命 和 上面的变量名 一样 竟然一样怎么办呢?
// 不要急 js解析器已经做了处理 同名的函数会替换掉 同名的 变量 现在就只剩下 a 函数块 自己了。

alert(a);              // 因为 上面 只剩下 a 函数了 所以现在就弹出 a函数的整个函数块。
a = 1;                  // a = 1 表达式赋值 所以就又把 a 函数给替换成了 变量 值为:1。

alert(a);              // 现在 弹出 的值就是被改变过的 a 值为 1;

function a(){          // 这个函数现在就没用了。

return false;
};


例子3,是讲函数参数的,前面说过可以把函数参数理解成函数内的局部变量,这样便于理解。
var a = 1;

function fn1(a){

alert(a);

a=2;

}

fn1();

alert(a);

/*

老规矩,先预解析参数、函数和变量提前,

var a=undefined;    //变量赋值undefined

function fn1(a){    //原装函数块奉上

alert(a);

a=2;

}

再来个逐行解读代码:

var a = 1;

读到fn1函数块,发现里面有参数,好!再来一遍预解析:

a = undefined;

接下来到12行了,fn1()执行的就是函数内最终返回值,此时函数局部作用域内从上到下开始执行代码,先是第9行alert(a), 返回值为undefined,再下面a=2就没有用,不去管它,所以fn1()函数的执行结果是弹出undefined。

最后读到alert(a);由于此时全局作用域中变量a已经被赋值1,所以最终弹出值1

*/
示例3:解释

var a;                                // a 变量 提前 当前值:undefind。(全局变量)function fn1(a){

alert(a);
a = 2;
};                                  // fn1 函数块提前 值为: 整个函数
// 该提前的都提前的现在开始 逐行 解读代码,
// 等等  有人会说那 参数 呢? 哈哈哈 不要着急还没到它呢。

var a = 1;                            // a = 1 赋值表达式 改变 变量 a 值为:1。function fn1(a){
var a;                        //参数被当成变量 解析到当前函数 顶部。
alert(a);                        // a 当前函数内 a 值为:undefined.
a = 2;                            // a = 2 复制表达式 无用
};                                  // 函数块 没有遇到调用 无用。
fn1();                                // 现在遇到函数fn1 的调用了 咱们就去它里面看看 。
// 调用成功后 弹 undefind。
alert(a);                         // 这个 还是调用 全局的变量 a 值 为 1。


    关注 捡贝壳


微信扫一扫关注公众号

0 个评论

要回复文章请先登录注册