js中预编译时的变量、函数提升

2019-05-27  本文已影响0人  毛毛_000e

先看一段代码的运行结果:

console.log(foo)      // foo(){ }

var foo=1;                 

console.log(foo)    // 1

function foo(){  

}

console.log(foo)    //1

console.log(foo())   //TypeError:foo is not a function

为啥会这样呢?

在解释器解析js代码的过程中,有一个预编译的过程,会把需要用到的变量声明和函数声明提升到方法体的最顶部,并且还有优先顺序之分:参数>函数>变量。需要注意的是,我们平时写函数的时候有2种写法:1>函数表达式 var fn=function fn(){ }

2>函数声明式 function fn(){} ,只有第二种函数声明式才会被提升,并且函数的提升是整个函数体的提升,同时变量也是只有声明被提升了,赋值没有被提升。

所以上面这段代码可以看成是这样的:

function foo(){}

console.log(foo) //这时候打印出来的就是foo函数

var foo=1 //这时候foo被重新赋值,变成了数值1

console.log(foo)  //重写后的foo是1

console.log(foo)    //1,同上

console.log(foo())   //因为foo被重写后已经是个Number类型的了,所以她不是函数,就会报错啦

艾玛,刚刚看到了一个更骚的题:

var b=10;

(function b(){ 

b=20

console.log(b)  //ƒ b(){  b=20;  console.log(b) }

})()

1、IIFE(立即执行函数)中的函数是函数表达式,不是函数声明

2、IIFE的函数名只在函数内部有效,并且函数名的绑定是常量绑定

3、对于一个常量进行赋值,在strict模式下回报错,非strict模式下静默失败

所以,这里的b函数是一个相当于用const定义的常量,内部无法进行重新赋值,如果在严格模式下会报错

上一篇 下一篇

猜你喜欢

热点阅读