文档章节

js预解析

风中一匹哈士奇
 风中一匹哈士奇
发布于 2017/08/31 23:14
字数 1351
阅读 6
收藏 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
昌平
程序员
私信 提问
JavaScript 为什么快--第二篇

上一篇,我们介绍了 V8 引擎的执行管道架构。本篇将着重介绍 V8 的语法解析过程。原视频 上一篇是产品经理思维;本篇则是理工科思维; 语法解析阶段对于前端来说尤其重要,相对 Noder 来说较...

秦粤
08/10
0
0
第112天:javascript中函数预解析和执行阶段

关于javascript中的函数:   1、预解析:把所有的函数定义提前,所有的变量声明提前,变量的赋值不提前   2、执行 :从上到下执行,但有例外(setTimeout,setInterval,ajax中的回调函数,...

半指温柔乐
2017/12/12
0
0
深入浅出JS - 变量提升(函数声明提升)

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

秋秋秋丷
05/17
0
0
Javascript作用域原理(转)

问题的提出 首先看一个例子: 运行结果是什么呢? 上面的问题, 我相信会有很多人会认为是: 因为会以为在echo中, 第一次alert的时候, 会取到全局变量name的值, 而第二次值被局部变量name覆盖, 所...

菜到没谱
2013/01/24
581
2
高性能JavaScript模板引擎原理解析

本文将用最简单的示例代码描述现有的 javascript 模板引擎的原理,包括新一代 javascript 模板引擎 artTemplate 的特性实现原理,欢迎共同探讨。 artTemplate 介绍 artTemplate 是新一代 ja...

李朝强
2013/07/29
0
0

没有更多内容

加载失败,请刷新页面

加载更多

区块链安全 - 以太坊短地址攻击

1 基础知识 EVM虚拟机在解析合约的字节码时,依赖的是ABI的定义,从而去识别各个字段位于字节码的什么地方。关于ABI,可以阅读这个文档: https://github.com/ethereum/wiki/wiki/Ethereum-C...

HiBlock
14分钟前
0
0
自定义函数及内部函数

变量的作用域 局部变量 global $Global及其他超全局数组 静态变量 仅初始化赋值 保留于内存直到response才销毁 global和static变量的区别 global:局部变量全局话 static:定义静态局部变量 函...

关元
15分钟前
0
0

中国龙-扬科
28分钟前
1
0
python包

https://www.lfd.uci.edu/~gohlke/pythonlibs/

陆朋
38分钟前
1
0
一文弄懂“分布式锁”,一直以来你的选择依据正确吗?

本文主要会关注的问题是“分布式锁”的问题。 多线程情况下对共享资源的操作需要加锁,避免数据被写乱,在分布式系统中,这个问题也是存在的,此时就需要一个分布式锁服务。 常见的分布式锁实...

Java干货分享
45分钟前
1
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部