js预编译

it2022-05-05  109

参考https://www.jianshu.com/p/78a4bf2fa12e

js是一门不需要编译的语言,由浏览器直接解释执行,但是es6中的模块都在讲述import和export的各种引用,和node 中的require的区别就是es6中的import是预编译时加载的,node中 的require是运行时加载的,还有一个说法是,es6中的import是静态编译阶段执行的,所以import的代码不可以写任何的一丝一毫的js逻辑判断或者运算的代码,例如import {f+‘oo’} from ‘./index.js’,这样写会报错,原因是因为import是静态执行的,打括号中的加法是运行时执行的

理解预编译前需要清除两个概念

函数声明(整体提升)变量赋值(声明提升)

1 .函数声明

function fn() { //函数声明,即声明一个函数,这种写法,脚本在执行之前会做预编译处理,函数声明有一个高的优先级的先编译后执行 } 2.变量赋值 var fn = function() {} 这种写法属于变量的赋值,函数在js中也是一种数据,匿名函数作为变量赋值给定义的变量,这种形式的写法,在编译阶段也会处理,但是只会给变量fn分配一个内存空间,不会初始化,初始化为undefined,具体的初始化会在程序执行阶段

例子:

function fn() { alert(“你好”) } fn() function fn() { alert("再见 ") } fn() 首先,这两个都属于函数声明,都会在预编译阶段处理,而函数名称相同,则后面声明的会覆盖前面的,所以在执行阶段就只会看到后面的,所以打印结果是两个 再见

下一个 var fn = function () {alert(‘你好’)} fn() fn = function(){alert(‘再见’)} fn() 首先判断两个都属于是变量赋值,而且两个变量名一样,所以在编译阶段只会分配一个内存空间存放变量fn的内容,当代码执行时候按照顺序执行和赋值,会先后弹出你好和再见 var fn // undefined fn = function () {alert(‘你好’)} fn() // ‘你好’ fn = function(){alert(‘再见’)} fn() // ‘再见’

?

function fn(){ alert(‘你好’) } fn() fn = function() { alert(‘再见’) } fn() 首先第一个属于函数声明,第二个是变量赋值,所以预编译处理完成后代码应该是这样的

var fn // undefined function fn() { alert(‘你好’) } fn() //你好 fn = function() { alert(‘再见’) } fn() // 再见

? window.alert(fn) function fn() {} window.alert('fn) var fn = 王淼 以上代码编译结束是这样的 var fn // undefined function fn() {} window.alert(fn) //function fn() {} window.alert(fn)//function fn() {} fn = 王淼

函数声明和变量声明会在预编译阶段被提升并且变量的提升是被最优先的提升的,变量提升会优先于函数声明提升,var fn不赋值为undefined然后提升函数声明 function fn(),此时因为函数声明在后所以它覆盖了fn变量给他复制为一个函数,当js引擎做完所有的这些提升的工作后js才会按照代码顺序来执行

另外需要注意的是js不是全文编译完成在执行,卫视块编译,即一个script块中预编译然后执行,再按顺序预编译下一个script块执行,但是此时上一个script块中的数据都是可以用的,而下一个块中的函数和变量则是不可用的

es6中编译时执行,就是在代码执行之前做一个预编译也可以叫静态编译,好处就是让你可以在执行任何代码前预初始化更多的模块结构这样如果尚未复制的export,能得到更好的错误信息,比如 ,一个let绑定会扔出异常,如果你在被复制之前就用到它的话,你可以得到清晰的错误信息,而一个动态模块对象上的属性如果还未赋值就被引用,得到的是undefined


最新回复(0)