js预编译

众所周知javascript是解释性语言,主要特点为解释一行执行一行。

而在js运行时会进行三件事:1语法分析 2.预编译 3.解释执行

语法分析会在代码执行前对代码进行通篇检查,以排除一些低级错误

预编译发生在代码执行的前一刻

解释执行顾名思义就是执行代码

我先给大家举几个预编译的小例子:

    var a = 123;

console.log(a);

此时他返回的值会是123;

但如果我们调换位置:

      console.log(a);

      var a = 123;      

      我们得到的结果便会是undefined。(由于js解释性语言的原因,先执行console.log,而由于预编译的原因浏览器并不会报错)

如果我们在次尝试不定义变量直接获取:

            console.log(a);  此时我们会发现浏览器会进行报错。//Uncaught ReferenceError: a is not defined

                                                                                                           这条语句提示我们a没有定义

到这里有些人会有疑问为什么在console.log前,后和不定义a会有如此大的差别,这就是预编译起到的作用

在具体讲解预编译之前要先帮大家了解几点小知识,如下:

预编译的前奏

  1. imply global 暗示全局变量:即任何变量,如果变量未经声明就赋值,此变量就为全局对象(window)所有。

        简单解释起来就是,如果在js中我们在赋值时经常先定义一个变量,如:var a = 123;
    
        此时123这个数字便被赋予了a这个变量,此时我们在控制台console.log(a)就会得到a的值123;
    
        这时就会我们就会有个疑问,如果我们没有定义变量直接进行赋值还会打印出值么。
    
        答案是肯定的,此时如果我们未定义变量直接赋值,如:
    
          b = 456;
    
      此时a会被认为是全局的一个对象,即window下的一个值,此时我们在控制台下console.log(b)同样可以得到b的值456。
    
      此时我们可以认为    b = 123   ————>   window.b  =456
    
  2. 一切声明的全局变量,全是window。

      简单说明就是我们 var  c = 789   ===>    window.c = 789(即:c =789)
    

预编译(粗浅版本)

下面我们来看一下对预编译最基本的肤浅理解(该理解非常粗浅无法解决复杂问题):

函数声明整体提升   

变量,声明提升

个人理解:在函数执行前函数声明(function(){})会整体提升至逻辑的最前方,

             变量则会把自身的声明提升到程序的最最前方。

//注释 var a =123;是变量声明+赋值

var  a:变量声明

a  = 123 变量赋值

在预编译时我们不看赋值,只把变量的声明提升,因此若在赋值前打印会提示undefined;

此时我们就可以理解之前的问题了:

    先打印再定义:

                console.log(a);

                var a = 123;  

在执行前var a提升至代码的最最前端 ,提升后我们再打印 a,由于此时a未被赋值因此打印提示undefined。

                 console.log(a);

  不定义:

                console.log(a);

此时由于没有a的定义,所以会报错提示a is not defined;即:a未定义。

看似很好理解但是如果代码稍微复杂便无法解决,例如:

        console.log(a);   fun

        function a(a) {

                    var  a  =  456;

                    var  a   =function  ()  {

            }

                   a();

        }

                var  a  =   123;

预编译的四步骤:

    1.创建GO/AO对象
    2.找形参和变量声明,将变量和形参名作为AO属性名,值为undefined
    3.将实参值和形参统一
    4.在函数体里面找函数声明,值赋予函数体
  举个例子:
  function f(a) {
  		console.log(a);
  		var a =123;
  		console.log(a);
  		function a() {}

		var b = function () { }
		function d() { }
  }
  f(1);
   1.创建AO对象:我们隐式的在函数中创建了一个AO的对象来盛放函数中的变量,此时对象中并没有值;

   2.找形参和变量声明,将变量和形参名作为AO属性名,值为undefined:我们在第二个过程中需按照变量和形参     AO = {
			a : undefined;
			b : undefined;
	}
	 3.将实参值和形参统一:此时将实参带入函数中由于在函数外 f(1),因此AO中a = 1
	 AO = {
			a : 1;
			b  ; undefined
	}
	 4.在函数体里面找函数声明,值赋予函数体:由于在函数中有 function a() {} ,这一函数因此此时AO中 a = function a() {}
	 AO = {
	 		a : function a() {};
	 		b : undefined;
	 		d : function d() {};
	 }
	 在进行完预编译后此时若执行函数则会以AO为基础对函数中的变量进行赋值:此时函数中有两次打印一次在函数开头,一次在函数为a赋值之后

再赋值前由于AO中值不变因此a所打印出的值为 function a() {}

在赋值后AO中a = 123,所以此时打印出的值为123。

一些题目的练习:

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值