对JS的预编译理解

JS引擎处理脚本的过程。

1.预编译过程
2.执行过程

脚本:
1.创建全局对象GO(windows)上下文
2. 加载脚本文件
3. 预编译
3.1找出所有的变量声明,按照变量名加入全局对象GO,如果已存在,忽略。
3.2找出所有的函数声明,按照函数名加入全局对象,如果存在同名变量或者函数,替换。
3.3非声明的变量和函数不用管。

1.如果遇到没有var的变量,都不是变量声明,全部都认为是windows的全局变量,不参与预编译

    console.log(aa);//这里报错,你找他要一个变量,它在windows上找了一遍,发现没有,报错
    aa = 5;
    console.log(aa);//这里有找到了

2.即使aa在函数中,aa也是全局变量,是运行时生效,不是预编译时生效


	console.log(aa);//这里报错,找不到这个变量,
	test();//尾部定义函数,头部调用,不会报错
	console.log(aa);//这里可以找到的
	function test(){
	   console.log('hello');
	   aa = 5;
	}
	console.log(aa);

3.脚本中,所有的变量声明,在脚本的预编译阶段完成,所有的变量声明与实际书写位置无关

   
    console.log(a);//undefined这里不报错,预编译
    var a = 5;
    console.log(a);//5

4.脚本中,所有的函数声明,在脚本的预编译阶段完成,所有函数的声明与实际书写的位置无关


    console.log(f);//没有报错,
    function f(){
        console.log('hello');
    }
5.脚本中,如果变量与函数同名,那么函数将覆盖变量

    console.log(f);//这里预编译,函数覆盖这个变量,输出这个函数
    var f = 123;
    console.log(f);//这里输出123,预编译阶段完成后执行,又给f变量赋值了一个123
    function f(){
        console.log('hello');
    }

6.脚本中,如果变量与函数同名,函数可以覆盖变量,但是变量无法覆盖函数


    console.log(f);//这里显示的是函数
    function f(){
        console.log('hello');
    }
    var f = 123;

7.脚本中,如果有多个函数同名,那么最后声明的函数将覆盖所有的前面所有的同名函数声明,
并且参数的个数是忽略的,也就是js根本就不支持重载

 
    console.log(f);//输出第二个函数,
    function f(x){
        console.log('hello1');
    }
     function f(y){
        console.log('hello2');
    }

预编译函数的调用
1.创建活动对象AO(Active Object) 上下文
2.预编译:
2.1:scope chain 作用域链
2.2:初始化 argments
2.3:初始化形参,将argments中的值赋值给形参
2.4:找出所有的变量声明,按照变量加入AO ,如果存在,忽略
2.5:找出所有的函数声明,按照函数名加入AO,存在则替换
2.6:this初始化
3.解释执行;

1.函数中,所有变量声明,在函数的预编译阶段完成,所有的变量声明与实际的书写位置无关,

    function f(){
        console.log(a);//undefined
        var a = 25;
        console.log(a);//25
    }
    f();

2.函数中,所有函数声明,在函数的预编译阶段完成,所有的函数声明与实际的书写位置无关、

  
    function f(){
        console.log(fin);//可以输出函数
        function fin(){
            console.log('hello');
        }
    }
    f();

3.函数中,如果变量与函数同名,那么函数将覆盖变量


    function f(){
        console.log(fin);//返回函数
        var fin = 123;
        console.log(fin);//返回123
        function fin(){
            console.log('hello');
        }
    }
    f();

4.函数中,只有函数能够覆盖变量,变量无法覆盖函数


    function f(){
        console.log(fin);//返回函数
        function fin(){
            console.log('hello');

        }

        var fin = 123;
        console.log(fin);//返回123
    }

    f();

5.函数中,后面的函数声明会覆盖前面的函数声明


    function f(){
        console.log(fin);//输出第二个函数
        function fin(x){
            console.log('hello1');
        }
        function fin(x){
            console.log('hello2');
        }
    }

    f();

6.函数预编译后,遇到需要访问的变量或者函数,优先考虑自己ao中定义的变量和函数,如果找不到,才会在其定义的上一层ao中寻找,直至到Go,再找不到就报错

    var scope = 'global';
    function f(){
        console.log(1,scope);//undefined
        var scope = 'local';
        console.log(2,scope);//local
    }
    f();
    console.log(3,scope);//gloabl

上代码执行过程如下

    Go.scope -> undefined
    GO.f -> function()

    Go.scope -> global
    GO.f -> function()

    Go.scope -> global
    GO.f -> function()
    f.AO.scope -> undefined

    Go.scope -> global
    GO.f -> function()
    f.AO.scope -> local
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值