JavaScript 函数预编译

变量提升与函数提升

变量提升:是变量声明提升,变量赋值没有提升。var a = 123,这是变量var a提升到最前面。

函数声明整体提升:函数不管写在哪里,都会被提升到逻辑的最前面。所以不管在哪里调

                                 用,本质上都是在声明后调用。

imply global暗示全局变量

任何变量未经声明就赋值,此变量就归全局对象window所有。window就是全局的域。

function test() {
    var a = b = 123;//首先给b赋值12-->window.b = 123, 然后声明a,在把b的值赋给a, a=123;
    console.log(a);//123 局部变量a
    console.log(b);//123 函数内可以访问全局变量b
}

test();
console.log(b)//123 全局变量b
console.log(a)//报错,因为全局上没有声明a,未经声明就访问就会报错!



function demo () {
    var c = 123;
}

demo();
console.log(window.c);//打印undefined,window是全局对象,访问一个对象没有的属性就是
                        undefined
console.log(c);//会报错, 变量c的作用域是函数内,在全局是没有声明这个变量的,这种访问方式是访问一个未声明的变量,所以就报错了。

预编译:解决执行顺序问题,预编译发生在函数执行的前一刻。

函数预编译四部曲

1.创建OA(Activation Object)对象 (执行期上下文,理解作用域,函数产生的执行空间库)。

2.找形参和变量,将其作为AO属性名,值为undefined。

3.将形参和实参统一(把实参传入到形参里)。

4.在函数体里找函数声明,值赋予函数体 (执行过程过中搜索变量,先看自己的AO,再看GO)

示例代码

function test(a, b) {
    console.log(a);
    c = 0;
    var c;
    a = 3;
    b = 2;
    console.log(b);
    function b() {};
    function d() {};
    console.log(b);
}

test(1)

1. AO: {//找形参和变量.        GO: {}
   a: undefined,
   b: undefined,
   c: undefined,
    
}

2. AO: {//将形参和实参统一
    a: 1,
    b: undefined,
    c: undefined
    
}
3. AO:{//找函数声明
    a: 1,
    b: function(){},
    d: function(){},
    c: undefined,
    
} 
4.执行console.log(a); 输入1  
  执行c=0 
  AO: {
    a: 1,
    b: function(){},
    d: function(){},
    c:0,
  }
  执行var c; 不用管,因为c已经在AO中了。
  执行a = 3,b = 2;
  AO:{
    a: 3,
    b: 2,
    d: function(){},
    c:0,
  }
  执行console.log(b); 输出 2;
  function b() {};function d() {}; 函数声明 不用管。
  再次执行console.log(b); 输入2;
    
  答案:1, 2, 2

一旦有重名的,既有a变量,又有a函数,又在第一条语句访问a, 那么a一定是函数。(因为函数声明在后一步,会覆盖变量声明)示例代码

function test(a, b) {
    console.log(a);
    console.log(b);
    var b = 234;
    console.log(b);
    a = 123;
    console.log(a);
    function a() {};
    var a;
    b = 234;
    var b = function (){}
    console.log(a);
    console.log(b);

}
test(1);

1. AO:{
    a:undefined,
    b:undefined,
}
2. AO: {
    a:1,
    b:undefined,
}
3. AO: {
    a: function a(){},
    b: undefined
}
4.执行console.log(a) 输出: function a(){}
  执行console.log(b) 输出: undefined
  执行var b = 234; 
  AO: {
    a: function a(){},
    b: 234,
  }
  执行console.log(b); 输出 234
  执行a = 123; 
  AO: {
    a: 123,
    b: 234,
  }
  执行console.log(a); 输出: 123
  执行b=234 
  AO: {
    a: 123,
    b: 234,
  }
  执行var b = function (){}
  AO: {
    
    a: 123,
    b:function(){},
 
  }
  执行console.log(a); 输出123,
  执行console.log(b); function(){}
全局预编译三部曲

1.生成一个GO对象,Golbal Object(window 就是GO)

2.找形参和变量声明,将形参和变量作为GO的属性名,值为undefined

3.在函数体里找函数声明,值赋予函数体

全局预编译 
console.log(a);//undefined  变量声明提升
var a = 123;


//例子2
console.log(a);//function a(){} //函数声明整体提升
var a = 123;
function a() {};

GO: {
   a:undefind,//找变量
}
GO: {
   a: function a(){} //找函数声明
}
执行console.log(a) 输出function a(){}

先有GO 再有AO 

在全局,先生成GO,在函数执行前一刻生成AO

console.log(test);
function test(test) {
    console.log(test);
    var test = 234;
    console.log(test);
    function test() {};
}
test(1);

var test = 123;

1.生成GO: {//有变量test
    test: undefined,
}
2.GO: {//有函数声明
    test: function test(){}
}
3.执行console.log(test) //在GO找test 输出 function test(){}
4.执行test(1) 生成AO
  AO: {
    test: undefined,//有变量test
  }
  AO: {
    test: 1, //实参形参统一   
  }
  AO: {
    test: function test(){}, //有函数声明
  }
5.执行console.log(test) //在AO中找,就近原则, 没有才去GO中找 输出 function test(){}
6.执行var test = 234; 
  AO : {
      test: 234,
  }
7.执行console.log(test); // 输出 234

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值