关于js解析执行有趣的事

Js代码
  1. varfoo=1;
  2. functionbar(){
  3. if(!foo){
  4. varfoo=10;
  5. }
  6. alert(foo);
  7. }
  8. bar();

Js代码
  1. vara=1;
  2. functionb(){
  3. a=10;
  4. return;
  5. functiona(){}
  6. }
  7. b();
  8. alert(a);

大家看输出的是什么?

第一题
10
第二题
1(局部和全局变量不同)


解释原因:

1.通俗解释

想简单理解的话,可以想象在第一个例子的函数bar进入时候第一行加一行
var foo = undefined

在第二个例子的函数b的第一行加一个
var a = undefined

解析作用域时候,该作用域里面不管哪行定义了东西,都可以简单想象成第一行声明了一个未初始化的同名变量。
(纯粹为了容易理解)

2.专业解释

这关系到JS解析顺序的问题,当JavaScript引擎解析脚本时,它会在预编译期对所有声明的变量和函数进行处理。
做如下处理:
1. 在执行前会进行类似“预编译”的操作:首先会创建一个当前执行环境下的活动对象,并将那些用var申明的变量设置为活动对象的属性,但是此时这些变量的赋值都是undefined,并将那些以function定义的函数也添加为活动对象的属性,而且它们的值正是函数的定义。
2. 在解释执行阶段,遇到变量需要解析时,会首先从当前执行环境的活动对象中查找,如果没有找到而且该执行环境的拥有者有prototype属性时则会从prototype链中查找,否则将会按照作用域链查找。遇到var a = ...这样的语句时会给相应的变量进行赋值(注意:变量的赋值是在解释执行阶段完成的,如果在这之前使用变量,它的值会是undefined)

换个角度来说,这个是函数体升迁的问题,如果是用 var fn = function() 这种形式来定义,那么 fn 会升迁,但是函数体不会升迁,因此会报告错误说 fn 不是一个方法(注意不是报告未定义),而如果使用 function fn() 来定义方法,那么 fn 和函数体会同时升迁,这样 fn() 是可以调用到结果的。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值