一:函数提升
console.log(global); // undefined var global = 'global'; console.log(global); // global function fn () { console.log(a); // undefined var a = 'aaa'; console.log(a); // aaa } fn();
之所以会是以上的打印结果,是由于js的变量提升,实际上上面的代码是按照以下来执行的:
var global; // 变量提升,全局作用域范围内,此时只是声明,并没有赋值 console.log(global); // undefined global = 'global'; // 此时才赋值 console.log(global); // 打印出global function fn () { var a; // 变量提升,函数作用域范围内 console.log(a); a = 'aaa'; console.log(a); } fn();
也就是说变量提升后,是会在内存中创建一个变量,但是没有赋值,所以是undefined状态。
了解一下js引擎原理:
在JS代码运行过程中:
引擎负责整个代码的编译以及运行,编译器则负责词法分析、语法分析、代码生成等工作而作用域则如我们熟知的一样,负责维护所有的标识符(变量)。
当我们执行上面的代码时,我们可以简单的理解为新变量分配一块儿内存,命名为global
,在运行的时候编译器与引擎还会进行两项额外的操作:判断变量是否已经声明:
1.首先编译器对代码进行分析拆解,从左至右遇见global
,则编译器会询问作用域是否已经存在叫global的变量了,如果不存在,则招呼作用域声明一个新的变量global,
若已经存在,则继续向下编译。
2.引擎遇见
var global = 'global'
时同样会询问在当前的作用域下是否有变量global
,若存在,则将global赋值为global。若不存在,则顺着作用域链向上查找,若最终找到了变量global则将其赋值global,若没有找到,则招呼作用域声明一个变量global并赋值为global.
补充说明,重复定义相同变量,由以上引擎只是可知,不会报错,只会由后续相同值覆盖内存值。
二、函数提升
js中创建函数有两种方式:函数声明式和函数字面量式。只有函数声明才存在函数提升!如:
console.log(f1); // function f1() {} console.log(f2); // undefined function f1() {} var f2 = function() {}
只所以会有以上的打印结果,是由于js中的函数提升导致代码实际上是按照以下来执行的:
function f1() {} // 函数提升,整个代码块提升到文件的最开始 console.log(f1); console.log(f2); var f2 = function() {}