文章目錄

解析机制

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. TensorFlow 实例一(一元线性回归)

    使用TensorFlow进行算法设计与训练的核心步骤: 准备数据 构建模型 训练模型 进行预测 问题描述: 通过人工数据集,随机生成一个近似采样随机分布,使得w = 2.0 ,b= 1,并加入一个噪声 ...

  2. Python 爬虫 爬取图片入门

    爬虫 网络爬虫(又被称为网页蜘蛛,网络机器人,在FOAF社区中间,更经常的称为网页追逐者),是一种按照一定的规则,自动的抓取万维网信息的程序或者脚本. 用户看到的网页实质是由 HTML 代码构成的,爬 ...

  3. 9.windows-oracle实战第九课--plsql

    一.oracle的pl/sql的概念 pl/sql是oracle在标准的sql语言上的扩展,不仅允许嵌入sql,还允许定义变量和常量,允许使用条件语句和循环语句,允许使用例外处理各种错误,这样使得它的 ...

  4. base64字符串转化成图片

    package com.dhht.wechat.util; import sun.misc.BASE64Decoder;import sun.misc.BASE64Encoder; import ja ...

  5. 使script.bin文件配置生效的驱动

    1.问题:在全志方案中如果需要设置上拉或者下拉模式,需要在script.bin(先转换为script.fex)中配置gpio口  如: 但是配置好后是不会生效的,需要写一个驱动来通过读取这个文件的gp ...

  6. Python 语言基础

    Python 语言基础 Python 开发环境 计算机组成 编程语言(计算机语言)是人们为了控制计算机,而设计的一种符号和文字的组合,从而实现向计算机发出指令. 形式是符号和文字的组合 目的是为了控制 ...

  7. RegexUtil

    package org.linlinjava.litemall.core.util; import java.util.ArrayList; import java.util.Collections; ...

  8. Spring-security整理

    出于某些原因,需要学习一下spring的安全框架.(研究半天,如果单单说用户认证和授权这块儿,我感觉还是shiro好用.) spring security介绍可以参考一下以下文档: (满满的羡慕啊)我 ...

  9. PostgreSQL中实现更新默认值(二)

    今天我们用表继承+触发器的方案,来实现表中的更新默认值.这也许是PostgreSQL里最佳的解决方案. 一. 创建一张表,作为父表 create table basic_update( t_updat ...

  10. 2)echo count(strlen("test")) 的输出为____

    结果是  1: 因为count测的是单元的数目,你的一个数组就是一个单元,所以 他的结果就是1 题目出处: https://www.nowcoder.com/test/question/done?ti ...