函数表达式和函数声明是定义函数的两种形式,不要弄混。函数表达式在JS中非常基础。函数表达式可以用来实现代码隐藏,变量隔离等等。函数声明具有变量提升的特性。
V8怎么处理函数声明
V8在执行JS的过程中,会先对其进行编译,然后再执行。
在编译阶段,如果解析到函数声明,V8会将这个函数声明转换为内存中的函数对象,并将其放到作用域中;如果解析到变量声明,也会将其放到作用域中,只是初始值会设置为undefined,表示变量还未使用。在执行阶段,V8会在作用域中查找需要使用的变量或是函数。这种在编译阶段,就将所有变量都提升到作用域的过程称为变量提升。
问题:为什么变量提升中函数声明是完整的函数对象,而普通的变量是undefined?
在变量提升阶段,V8不会执行赋值的表达式,只会分析基础的语句,比如变量的定义,函数的声明。而函数声明是语句,所以V8会在编译阶段对其进行变量提升操作,因为函数是对象,所以V8就会将整个函数对象提升到作用域中。而普通变量的赋值是表达式,所以不会在编译阶段执行,仅保留初始值undefind。
V8怎么处理函数表达式
在一个表达式中使用function来定义一个函数,a=function(){},就把该函数称为函数表达式。V8在编译阶段不会处理函数表达式。
var getName = function(name){
return name;
}
函数表达式和函数声明的区别:
- 函数表达式是在表达式语句中使用function的,a=function(){}这种方式。
- 函数表达式中,省略函数名称,可以创建匿名函数。
- 函数表达式可以被当做即时调用的函数表达式-IIFE。
IIFE-立即调用函数表达式
(function(){
....
})()
IIFE也是一个表达式,所以V8编译阶段并不会为该表达式创建函数对象。IIFE优点是不污染环境,函数和函数内部的变量都不会被外部访问到,这样就适合做对象封装。另外函数立即表达式是立即执行的,如果赋值给一个变量,变量存储的不是IIFE本身,而是IIFE执行后的结果。
总结
函数声明的本质是语句,函数表达式的本质是表达式。
V8编译阶段仅对语句做提升,在执行阶段做表达式的赋值。
V8在编译阶段,对函数声明和变量声明会做变量提升到作用域中。变量提升到作用域时,会设置默认值undefined;函数声明提升到作用域时,V8会在内存中创建该函数对象,并提升整个函数对象。
函数表达式不会被变量提升,但是可以使用IIFE来封装变量,函数等,起到变量隔离和代码隐藏的作用。