文档章节

js预解析

风中一匹哈士奇
 风中一匹哈士奇
发布于 2017/08/31 23:14
字数 1351
阅读 3
收藏 0
点赞 0
评论 0

 

首先看一下什么是预解析:

预解析:在当前作用域下,js运行之前,会把带有var和function关键字的事先声明,并在内存中安排好。然后再从上到下执行js语句。

预解析只会发生在通过var定义的变量和function上。

全局作用域其实是全局对象的作用域,任意地方都可以访问到(如果没有被函数作用域覆盖)。函数作用域则是整个函数范围,不论它是在函数的什么位置声明的!

作用域的嵌套

当一个块或者一个函数嵌套再另外一个块或者函数中,就发生了作用域的嵌套,因此,在当前的作用于中无法找到某个变量的时候,引擎就会在上一级的作用域中继续查找,直到找到(全局)这个变量为止,如果在全局作用域中找不到这个变量,就会报错。

不过,在ES6中,新增了一个块级作用域,

在es5中没有块的概念,在es6中才有

Eg:

for(var i = 0;i<arr.length;i++){

let a = 2;

console.log(a);

}

这个for循环花括号内就是个块,其内部声明的变量是局部变量,而不像es5中为全局变量。

这里说明一点,就是let声明的变量必须在调用之前,否则会报ReferenceError异常

eg:

function f(){

    console.log(a);

    let a="hello";

}

f();            //这里a虽然被提升,但却报了引用错误(ReferenceError)

 

这里还引申出一个东西,就是词法作用域   

词法作用域就是在写代码的时候,将变量和作用域写在哪里来决定的,也就是代码在编写的过程中,体现出来的作用范围,代码一旦写好了,作用域的范围就已经确定好了,记住下面几条规则

词法作用域的规则:

1、函数允许访问函数外的数据

2、整个代码结构中只有函数可以限定作用域

3、作用域的规则首先要使用提升(函数声明提升和变量声明提升)规则

4、如果当前作用域中有一个变量,就不考虑外面的同名变量

接着开始咱们正题

首先:

一、1变量声明:

var x;  //变量声明

var x=10;  //变量声明并赋值

x=10;  //定义全局变量并赋值

2函数声明

function fn(){}  //函数声明并定义,这个叫做函数声明

var fn=function(){};  //这个叫做函数表达式,实际上定义了一个局部变量fn和一个匿名函数,然后把这个匿名函数赋值给了fn

至于优先级,函数声明>函数表达式,在js解析的时候,函数声明会提到最顶端,最先解析。

二. 变量提升

举个栗子:

var a=2;

    function f(){

        console.log(a);

        if(true){

            var a="hello";

        }

    }

f();

这里其实打印出来的应该是undefined。

如果说这段代码被翻译成这样,能看明白吗?

    function f(){   //函数声明,放上面

        var a;      //定义,但是没有赋值

        console.log(a);   //undefined

        if(false){

            var a="hello";

        }

}

var a;

    a = 2;

f();

这样是不是就一目了然了,这里要说的就是,变量提升,只提升声明,不提升赋值,当声明过,但是没有赋值的a打印的时候,a为undefined。

 

三、重复声明

但是如果我再声明变量的时候不小心重复声明了怎么办,会出现什么情况,这就是变量重复声明:看栗子

var a=1;

console.log(a);

if(true){

    var a=2;

    console.log(a);

}

console.log(a);  //这里结果输出的是 1 2 2

虽然看起来a申明了两次,但上面说了,js的var变量只有全局作用域和函数作用域两种,并且申明会被提升,因此实际上a只会在最顶上开始的地方申明一次,var a=2的申明会被忽略,仅用于赋值。翻译过来就是

Var a;

Var a;   //重复声明则被忽略

a=1;

console.log(a); //1

If(true){

a = 2;

console.log(a);   //2

}

console.log(a);   //2   这里a被重新赋值,所以为2;

 

四、那如果变量和函数声明同时提升呢?

下面对比两个栗子

栗子一:console.log(foo);

function foo(){};

var foo="I am text";

 

栗子二:console.log(foo);

var foo=function(){};

var foo="I am text";

 

他们分别打印什么呢?

第一个:打印出来function foo(){}       第二个打印 undefined

为啥呢?这就是说第一点的时候提到的优先级,函数声明会提到最上面,

1、函数声明被提升到最顶上;

2、申明只进行一次,因此后面var foo='i am text'的声明会被忽略。

第一个:

function foo(){};

Var foo ;

console.log(foo);

foo="I am text";

第二个:

var foo ;

var foo;

console.log(foo);

foo=function(){};

foo="I am text";

所以才会出现以上结果。

 

Js预解析总结

1、所有声明都会被提升到作用域的最顶上

2、同一个变量申明只进行一次,并且因此其他声明都会被忽略

3、函数声明的优先级优于变量申明,且函数声明会连带定义一起被提升

 

这篇文章是参考了一些文章,以及自己的一些体会写的,有不足的地方请指出,谢谢!

© 著作权归作者所有

共有 人打赏支持
风中一匹哈士奇
粉丝 4
博文 8
码字总数 7492
作品 0
昌平
程序员
深入浅出JS - 变量提升(函数声明提升)

前言 在我们的日常工作中,变量无处不在。更加深入的去了解它,能够使得自己的JS水平更上一层楼, 从变量提升这个小知识点着手,让我们一起来深入了解JS吧! 变量提升的小栗子 分析原因 JS引...

秋秋秋丷 ⋅ 05/17 ⋅ 0

JSON,异步加载(学习笔记)

JSON是一种传输数据的格式(以对象为样板,本质上就是对象,但用途有区别,对象就是本地用的,json是用来数据传输的,前端与后端的数据通信) JSON是静态类(不需要构造),类似于Math,内部...

Mrs_CoCo ⋅ 04/23 ⋅ 0

再谈DOMContentLoaded与渲染阻塞—分析html页面事件与资源加载

浏览器的多线程中,有的线程负责加载资源,有的线程负责执行脚本,有的线程负责渲染界面,有的线程负责轮询、监听用户事件。 这些线程,根据浏览器自身特点以及web标准等等,有的会被浏览器特...

zhoulujun ⋅ 05/22 ⋅ 0

移动端本地 H5 秒开方案探索与实现

欢迎大家前往腾讯云+社区,获取更多腾讯海量技术实践干货哦~ 企业微信移动端项目中有需求要展示数据趋势的可视化图表,经过调研,最终决定以单页面 H5 来完成,对 APP 里的一些使用 H5 实现的...

腾讯云加社区 ⋅ 06/11 ⋅ 0

go做静态资源服务器(http2,https),前端无法正常解析js

问题: 想尝试一下golang的http2功能,但是遇到一个问题, js文件无法正常解析... go version go1.10.2 windows/amd64 详情: 后端代码 前端代码: 项目结构: 不能正常解析的情况 前端错误信息: R...

漂泊的树叶 ⋅ 06/05 ⋅ 0

细谈在HTML中使用JavaScript

细谈在HTML中使用JavaScript 前言 JavaScript是浏览器的内置脚本语言。当网页中嵌入了JavaScript脚本,浏览器加载网页时,就会执行脚本,从而操作浏览器,实现各种动态效果 JavaScript代码嵌...

幸运券发放 ⋅ 05/25 ⋅ 0

Gulp和Webpack工具的区别

引用知乎的回答:https://www.zhihu.com/question/37020798 怎么解释呢?因为 Gulp 和 browserify / webpack 不是一回事 Gulp应该和Grunt比较,他们的区别我就不说了,说说用处吧。Gulp / Gr...

easonjim ⋅ 2016/12/24 ⋅ 0

四月前端知识集锦(每月不可错过的文章集锦)

目前自己组建的一个团队正在写一份面试图谱,将会在七月中旬开源。内容十分丰富,第一版会开源前端方面知识和程序员必备知识,后期会逐步写入后端方面知识。因为工程所涉及内容太多(目前已经...

夕阳 ⋅ 05/02 ⋅ 0

JS学习系列 07 - 标签声明(Label Statement)

1. 引言 假设有这么一道题: 我想要当 j = 2 的时候就退出所有的for语句,打印最后的 done ,你会怎么做? 可能有的同学会想到这样: 这样可以实现,但是又多写了一个函数,那么有没有别的办...

liuxuan ⋅ 05/30 ⋅ 0

WebAssembly 时代,Rust 也想成为 Web 语言

目前 Mozilla 正在基于 WebAssembly 可移植代码格式研发 JavaScript 和 Rust 之间的桥梁——wasm-bindgen,意义是提高 JavaScript 和 Rust 之间的互操作性。Mozilla 这么做是想让 Rust 成为类...

开源中国 ⋅ 04/10 ⋅ 0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

从零开始搭建Risc-v Rocket环境---(1)

为了搭建Rocke环境,我买了一个2T的移动硬盘,安装的ubuntu-16.04 LTS版。没有java8,gcc是5.4.0 joe@joe-Inspiron-7460:~$ java -version程序 'java' 已包含在下列软件包中: * default-...

whoisliang ⋅ 14分钟前 ⋅ 0

大数据学习路线(自己制定的,从零开始学习大数据)

大数据已经火了很久了,一直想了解它学习它结果没时间,过年后终于有时间了,了解了一些资料,结合我自己的情况,初步整理了一个学习路线,有问题的希望大神指点。 学习路线 Linux(shell,高并...

董黎明 ⋅ 20分钟前 ⋅ 0

systemd编写服务

一、开机启动 对于那些支持 Systemd 的软件,安装的时候,会自动在/usr/lib/systemd/system目录添加一个配置文件。 如果你想让该软件开机启动,就执行下面的命令(以httpd.service为例)。 ...

勇敢的飞石 ⋅ 22分钟前 ⋅ 0

mysql 基本sql

CREATE TABLE `BBB_build_info` ( `community_id` varchar(50) NOT NULL COMMENT '小区ID', `layer` int(11) NOT NULL COMMENT '地址层数', `id` int(11) NOT NULL COMMENT '地址id', `full_......

zaolonglei ⋅ 30分钟前 ⋅ 0

安装chrome的vue插件

参看文档:https://www.cnblogs.com/yulingjia/p/7904138.html

xiaoge2016 ⋅ 33分钟前 ⋅ 0

用SQL命令查看Mysql数据库大小

要想知道每个数据库的大小的话,步骤如下: 1、进入information_schema 数据库(存放了其他的数据库的信息) use information_schema; 2、查询所有数据的大小: select concat(round(sum(da...

源哥L ⋅ 55分钟前 ⋅ 0

两个小实验简单介绍@Scope("prototype")

实验一 首先有如下代码(其中@RestController的作用相当于@Controller+@Responsebody,可忽略) @RestController//@Scope("prototype")public class TestController { @RequestMap...

kalnkaya ⋅ 今天 ⋅ 0

php-fpm的pool&php-fpm慢执行日志&open_basedir&php-fpm进程管理

12.21 php-fpm的pool pool是PHP-fpm的资源池,如果多个站点共用一个pool,则可能造成资源池中的资源耗尽,最终访问网站时出现502。 为了解决上述问题,我们可以配置多个pool,不同的站点使用...

影夜Linux ⋅ 今天 ⋅ 0

微服务 WildFly Swarm 管理

Expose Application Metrics and Information 要公开关于我们的微服务的有用信息,我们需要做的就是将监视器模块添加到我们的pom.xml中: 这将使在管理和监视功能得到实现。从监控角度来看,...

woshixin ⋅ 今天 ⋅ 0

java连接 mongo伪集群部署遇到的坑

部署mongo伪集群 #创建mongo数据存放文件地址mkdir -p /usr/local/config1/datamkdir -p /usr/local/config2/data mkdir -p /usr/local/config3/data mkdir -p /usr/local/config1/l......

努力爬坑人 ⋅ 今天 ⋅ 0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部