js的预解析详细分析

js的预解析:

为什么我们用var定义一个变量a,在这行代码之前打印a却不报错,而是得到undefined?又或者函数为什么可以随意放置,在哪里调用都可以应用,这是什么原理?

其实这样的情况,都是因为JavaScript中有一种机制,就是:“预解析机制”。

1.1   预解析原理

简单来说,预解析就是——在当前作用域下,js在运行之前,会把带有var和function关键字声明的变量先声明,并在内存中安排好。然后再从上至下解析js语句。

var 预解析

js 在正常解析之前,会快速的把 script (或者 funciton )中的 var 声明及声明的名字,提升到代码块(作用域)的最前面。

function 预解析

js 在正常解析之前,会快速的把 script (或者 funciton )中的 function 及内容提升到代码块(作用域)的最前面,跟在 var 声明之后。

1.2 var声明

通过var声明的变量,进行预解析的时候:先声明变量,不管变量有没有赋值,声明时都赋值为undefined。

事例:

console.log(a); //undefined

var a = 1;

console.log(b); //undefined

var b = function(){}//注意,这是个函数表达式

事例:

第1步:

console.log(a);// undefined,此时读取变量a

var a = 10;

//解释:在执行代码之前,js会预解析代码,代码中如果有变量声明和函数声明的话,那么便将变量声明和函数声明置顶;

也就是说,以上代码在js运行中,是如下执行的:

var a;//变量声明置顶设置,但不赋值

console.log(a); //undefined

a = 10;//变量在此处赋值。

第2步:

console.log(a); //undefined

console.log(b); //undefined

var a = 10;

var b = function(){}//同样是var声明的函数进行置顶设置,但是不赋值;

第3步:

var a = 10;

var a = function(){};

console.log(a); //function (){}

相当于:

var a = 10;

a = function(){};

console.log(a); //function (){}

var定义的a,是同一个a,不会产生不同的变量,只是让a改变了值,由数值变成了函数。

反之亦然,

var a = function(){};

var a = 10;

console.log(a); //10

var声明按照赋值顺序执行,同名的var声明,后者的声明不会产生新变量,只是值会覆盖前者。

1.3 function声明

js 在正常解析之前,会快速的把 script (或者 funciton )中的 function 及内容提升到代码块(作用域)的最前面,跟在 var 声明之后。

function进行预解析的时候,不仅是声明而且还定义了函数体,在内存中会开辟一块内存空间,存储的是函数体的字符串,但是代码不会执行。只有函数调用以后才执行。

事例:

第1步

console.log(a); //打印结果不是a,而是函数a()的方法体!证明函数a跟在var声明之后被声明的。

var a = 10;

function a(){return 100;};

其实相当于:

var a;

function a(){return 100;};

a = 10;

第2步

var a = 10;

function a(){return 100;};

console.log(a); //10

解释请看上一步的代码解释。

注意:

(1) 同名的var声明和同名的函数声明(不是函数表达式,用function声明的函数),不管二者书写先后顺序,函数声明会覆盖掉var声明的变量(因为它的置顶顺序低于var声明);

(2) 同名的var声明,后者会被忽略;

(3) 同名的函数声明,后者会覆盖前面的(这只是函数声明按自上而下的顺序执行罢了)。

课堂练习,思考一下结果:

var a = 10;

function a(){return 100;};

var a = function (){return 10000;};

console.log(a);

注意问题:

(1) 预解析,不会超出script标签,前面访问不到后面的定义

(2) 后面script标签中可以访问呢前面script标签中的js,因为js是从上至下执行的。

(3) 函数内部同名变量的声明高于传入的同名参数

var a = 10;

function fn(a){

var a = 20;

console.log(a);//20

}

fn(a);

(4) 函数内参数的声明高于外部同名变量的声明。

var a = 10;

function fn(a){

console.log(a);//100

}

fn(100);

1.4 预解析应用

var a = 1;

function b(){

a = 10;

return;

function a(){

    console.log(a);

}    

}

b();

console.log(a);

思考,打印结果?

注意:预解析既可置顶提升变量也可以提升函数。

代码会按照如下情况执行:

var a;

function b(){//注意,函数也会提升

function a(){//注意,函数也会提升,而不是被return结束掉了。

    console.log(a);

}    

a = 10;//注意,作用域链的应用,它的查找顺序是由内而外,就近原则!所以虽然函数a没有被调用过,但是这里的赋值,是赋值给b函数中的a函数的!

return;

}

a = 1;

b();

console.log(a);

课堂练习:

var a;

function a(){

console.log(10);

}

console.log(a);

function a(){

console.log(10);

}

var a;

console.log(a);

function a() {

  var b = 1;

}

console.log(a);

var a = function() {

var b = 2;

};
  
文章来源:https://www.cnblogs.com/mijuntao/p/15073657.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值