深入理解函数的预解析和作用域

先了解什么是预解析

预解析步骤:
第一步:代码还没执行,预览页面之前,写完之后
1、找程序中的var关键字,如果找到了提前给var定义的变量赋值undefined;
2、找程序中的普通函数,如果找到了,函数提升,将整个函数赋值给函数名;
3、如果找到的var的名字和函数名相同,函数优先。

第二步:逐行解析代码,按照上下文顺序。如果碰到函数定义,忽略。

看代码理解:
例1:

function fun() {
    console.log(n);
    var n = 23;
    console.log(n)
}
var n = 12;
 fun(n)

输出结果:
undefined
23

分析:
1、fun函数开始之前执行,将var n 提前执行,初始化为undefined。
2、函数传入n并没有使用,忽略
3、开始执行函数代码第2行,输出undefined
4、执行执行函数代码第3行,此时n赋值为23,即将n值重置为23
5、执行执行函数第4行,输出改变后的n
综上,得知预解析的原理(针对有var的变量提前赋初始值)
注:fun函数内部有解析域
扩展:以上程序改为使用let 定义变量,以上程序会报错,因为let不会使变量提升

继续深入
例2:

var length = 100;
function f1() {
    console.log(this.length)
}
var obj = {
    x: 10,
    f2: function (f1) {
        f1();
        arguments[0]()
    }
}
obj.f2(f1, 1);
f1()

输出结果:
undefined
2

分析:
1、预解析,初始化:length、obj、f1,并赋值为undefined
2、赋值:

  1. 变量length赋值为100
  2. 函数变量f1赋值为函数
  3. 变量obj赋值为对象

3、执行第12行,obj.f2(f1, 1) 调用对象的f2函数执行,传入形参f1和1
4、执行第8行,obj对象的f2接收实参f1,并执行f1函数
5、同上,f1执行无调用者,作用域为全局,this指向window,输出全局变量length,即100
6、执行第9行,arguments[0] () 执行,obj.f2的第一个参数是f1,第二的参数是arguments[1]为1,以此类推。
7、arguments[0] () 看上去是f1(),应该输出100。注意 arguments[0]和f1的作用域不相同,f1()是直接执行f1,无调用者,作用域为全局作用域。但是arguments[0]作用域为arguments对象,即this为arguments,
则应该输出2,因为arguments对象的属性length为2

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值