文章目錄

解析机制

JavaScript是一门解释型的语言 , 想要运行js代码需要两个阶段

  1. 编译阶段: 编译阶段就是我们常说的JavaScript预解析(预处理)阶段,在这个阶段JavaScript解释器将完成把JavaScript脚本代码转换到字节码
  2. 执行阶段: 在编译阶段JavaScript解释器借助执行环境把字节码生成机械码,并从上到下按顺序执行

预解析时做什么

var , function声明的变量提升

  首先,创建一个当前执行环境下的活动对象,然后将用 var 声明的变量设置为活动对象的属性(也就是将其添加到活动对象当中)并将其赋值为undefined,然后将 function 定义的函数 也添加到活动对象当中

1
2
3
4
5
6
7
if( false ){
var aa = 20;
var bb = 30;
} function (){};
function BB(){};

var定义的aa,bb以及function定义的AA(),BB()都会被变量提升到window对象下面 提升后等同于如下代码:

1
2
3
4
5
6
7
8
var aa;
var bb;
function (){};
function BB(){};
if( false ){
aa = 20;
bb = 30;
}

注: 不是用var 定义的变量具有全局性, 但是并不会被提升, 只有在第一次执行到时才会出现在全局作用域中

函数声明与函数表达式在预解析的区别

  首先,我们知道解析器会对function定义的函数(也就是函数声明)在代码开始执行之前对其实行函数声明提升(function declaration hoisting),所以在函数声明之前调用该函数是不会在执行期间报错,但是函数表达式不同,函数表达式用 var 声明,也就是说解析器会对其变量提升,并对其赋值为undefined,然后在执行期间,等到执行到该var 变量的时候再将其变量指向一个function函数,所以在函数表达式之前执行该函数是会报错的。

1
2
3
4
5
AA();
function (){}; BB();
var BB = function(){};

AA();不会报错,因为是以function的变量提升,BB()会报错,因为是以var的变量提升,提升后代码等同于如下:

1
2
3
4
5
6
function (){};
var BB; AA();
BB();
BB = function(){};

注意: 函数声明提升以后并不会执行内部的代码, 在其内的变量声明也不会起作用, 而是等到函数第一次被调用时才会执行 如:

1
2
3
4
5
6
7
var AA = function(){
console.log(' AA ');
} function BB(){
console.log(' BB ');
}

单独这一段代码并不会起作用, 只有执行:

1
2
AA(); // 输出 AA
BB(); //输出 BB

function 覆盖

 若定义了两个同名的函数,则在预解析期间后面一个会覆盖签名一个

大专栏  js作用域其二:预解析ass="gutter">
1
2
3
4
5
6
7
8
9
AA();   // 输出 I am AA_2;
function (){
console.log('I am AA_1');
}; AA(); // 输出 I am AA_2;
function AA(){
console.log('I am AA_2');
}

提升后其代码等同于如下:

1
2
3
4
5
6
7
8
9
10
function AA(){
console.log('I am AA_1');
} function AA(){
console.log('I am AA_2');
} AA();
AA();

可以看到这是正常的函数声明覆盖

预解析把变量或函数解析到其运行时的环境中

解析器将变量提升并不是将所有的变量都提升到window对象下面,其提升的原则是提升到变量运行的环境(变量生效的词法作用域)顶端

1
2
3
4
5
6
7
aa = "I am aa";
function AA(){
console.log(aa); // 输出 aa 是 undefined
var aa = "I am aa in a function";
console.log(aa); //输出 aa 是 I am aa in a function
}
AA();

这里 aa 被变量提升,但是aa 没有被变量提升到 window下面,而是被提升到其运行的环境 (function(){ })() 中去,也就是等同于

1
2
3
4
5
6
7
8
aa = "I am aa";
function AA(){
var aa;
console.log(aa); // 输出 aa 是 undefined
aa = "I am aa in a function";
console.log(aa); //输出 aa 是 I am aa in a function
}
AA();

JavaScript“预解析”分段进行

所谓分段进行是按照< script >标签来分块进行预解析

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<script>
AA(); // 输出 AA2;
function AA(){
console.log('AA1');
} function AA(){
console.log('AA2');
}
</script> <script>
function AA(){
console.log('AA3');
}
</script>

上面例子说明function函数声明是分块的,然而至于var变量的提升经过反复验证是不分块的( 此处如有不同意见请指教 )

参考

javascript解析机制——预解析
本文是在此篇博客的基础上进行了修改与扩充

js作用域其二:预解析的更多相关文章

  1. JS作用域概念-预解析规则

    // 作用域: // 域:空间.范围.区域…… // 作用:读.写 script 全局变量.全局函数 自上而下 函数 由里到外 {} 浏览器: “JS解析器” 1)“找一些东西” :var funct ...

  2. 14 (H5*) JS第4天 函数、作用域、预解析

    目录 1:函数的其他定义 2:函数作为参数 3:函数作为返回值 4:作用域 5:作用域链 6:预解析 7:预解析分段 复习 <script> /* * 复习: * 函数:把一些重复的代码封 ...

  3. JavaScript (四) js的基本语法 - - 函数练习、arguments、函数定义、作用域、预解析

    个人博客网:https://wushaopei.github.io/    (你想要这里多有) 一.函数练习 1.求最值 // - 求2个数中的最大值 function getMax(num1, nu ...

  4. JS基础研语法---函数基础总结---定义、作用、参数、返回值、arguments伪数组、作用域、预解析

    函数: 把一些重复的代码封装在一个地方,在需要的时候直接调用这个地方的代码就可以了 函数作用: 代码重用 函数的参数: 形参:函数定义的时候,函数名字后面的小括号里的变量 实参:函数调用的时候,函数名 ...

  5. javascript作用域、预解析笔记

    1.作用域     一般情况下,一段代码中所用到的名字并不总是有效可用的,     而限定这个名字(变量)的可用性的代码范围就是这个名字的作用域,可用有效的减少变量名冲突     2.js的作用域(e ...

  6. javascript里面的闭包,作用域,预解析

    函数的作用域 1.全局变量=公用卫生间 2.局部变量=次卧卫生间      局部变量 全局无法使用      局部声明变量不加var的话就变成全局变量(不推荐使用) 3.闭包=次卧的可以用自己的卫生间 ...

  7. JS中的预解析

    js预解析对于很多学习web前端开发的新手们很困扰,总是很难搞懂到底是个什么东西,今天零度就为大家简单的分析一下,争取让大家都明白! 首先,看一下下面的代码: alert(a); var a = 1; ...

  8. JS基础语法---预解析

    预解析:就是在解析代码之前   1. 预解析做什么事? 把变量的声明提前了----提前到当前所在的作用域的最上面 函数的声明也会被提前---提前到当前所在的作用域的最上面   举例: function ...

  9. 函数(定义、参数、return、变量、作用域、预解析)

    一.函数定义 1.方式一       function 函数名(参数){  函数体  }——————函数声明的方法 function fn(a){ console.log(a); }: 2.方式二  ...

随机推荐

  1. iOS个人中心渐变动画、微信对话框、标签选择器、自定义导航栏、短信验证输入框等源码

    iOS精选源码 简单的个人中心页面-自定义导航栏并予以渐变动画 程序员取悦女票的正确姿势---Tip1(iOS美容篇) iOS 前台重启应用和清除角标的问题 微信原生提醒对话框3.0 JHLikeBu ...

  2. 5)PHP,可变变量

    所谓可变变量,就是一个变量的名,又是一个变量. 可变变量的语法是php的很特殊的语法——其他语言中少见. $v1 = “abc”; //这是一个字符串变量,其内容是字符串“abc” $abc = ; ...

  3. 第二个--关于led灯的代码总结

    又要继续奋斗啦,不然就交白卷了: 1---自己注意,就是那个板子上有8个led灯,这个灯呢,没哟甩端口直接控制模式用573锁存器来控制的,为的是啥呢,因为你的芯片就那么几个引脚  ,你就单单把引脚拿来 ...

  4. linux 信号量sem实现 生产者—消费者(线程间通信)

    #include<pthread.h> #include<stdlib.h> #include<stdio.h> #include<unistd.h> ...

  5. myeclipse 编写java代码提示 dead code 原因

    经常使用MyEclipse或Eclipse编辑器编写java代码的程序员,可能经常遇到一个黄线警告提示:dead code:一般程序员遇到这些问题都会置之不理,反正也不影响程序的编译执行.对,这不是b ...

  6. 吴裕雄--天生自然C语言开发:递归

    void recursion() { statements; ... ... ... recursion(); /* 函数调用自身 */ ... ... ... } int main() { recu ...

  7. 计算a^b==a+b在(l,r)的对数Codeforces Round #597 (Div. 2)

    题:https://codeforces.com/contest/1245/problem/F 分析:转化为:求区间内满足a&b==0的对数(解释见代码) ///求满足a&b==0在区 ...

  8. logstash nested内嵌字段 field protobuf解码 codec 的解决办法

    logstash nested内嵌字段 field protobuf解码 codec 的解决办法 主要需求 logstash-codec 下https://www.elastic.co/guide/e ...

  9. 74cms_3.5.1 宽字节注入

    第一次进行CMS的代码审计,我选择了2014年发布的74CMS 3.5.1,历史比较久远的CMS往往存在更多的问题,虽然技术上难度不大,但是在思路方面给了我很大的启发.下面我根据我的思路给大家分享一下 ...

  10. The Chosen One+高精度

    题目描述 Welcome to the 2017 ACM-ICPC Asia Nanning Regional Contest. Here is a breaking news. Now you ha ...