JS 变量提升
参考链接:
什么是变量提升? 举个例子
console .log (a) var a = 10
为什么打印的是 undefined 呢?就是由于 js 的变量提升机制,代码执行前,浏览器会将带有var
, function
关键词的变量提前进行声明(默认值就是 undefined)。在变量提升解读啊,带var
的只是声明还没有被定义,带function
的已经声明和定义。
示例:
var a = 12 var b = ab = 1 function sum (x, y ) { var total = x + y return total } sum (1 , 2 )
变量提升只发生在当前的作用域
带 var 和不带 var 的区别
全局作用域中可以不带var
声明变量,但是建议带上,不带相当于给window
设置一个属性
私有作用域,带var
的是私有变量,不带的会向上级作用域查找
全局中使用var
声明的变量会映射到window
下称为属性
a = 12 console .log (a) console .log (window .a ) var a = (b = 12 ) var a = 12 b = 12
题目 下面来个思考题
console .log (a, b)var a = 12 , b = 'bbb' function foo ( ) { console .log (a, b) var a = (b = 13 ) console .log (a, b) } foo ()console .log (a, b)
4 处我的回答是:
正确的应该是
其中第二个就是局部作用域的变量提升引起的,可以看成这样
function foo ( ) { var a = 13 b = 13 }
所以 a 是变量提升,log 的是 undefined,b 是向上找到 window.b
再看一题:
a = 2 function foo ( ) { var a = 12 b = 'bbb' console .log ('b' in window ) console .log (a, b) } foo ()console .log (b)console .log (a)
我的回答是:
因为 b 没有带var
,所以就直接设置的 window.b 属性
下一题:
function foo ( ) { console .log (a) a = 12 b = '林一一' console .log ('b' in window ) console .log (a, b) } foo ()
可能先入为主以为可以正常 log,实际上是直接报错ReferenceError: a is not defined
因为第一个 log 那里并没有找到 window.a,下面的 a 也没有变量提升,所以直接报错
下一道是一个经典面试题:
fn ()console .log (v1)console .log (v2)console .log (v3)function fn ( ) { var v1 = (v2 = v3 = 111 ) console .log (v1) console .log (v2) console .log (v3) }
我的答案是:
等号左边下的变量提升 函数左边的变量提升
print ()function print ( ) { console .log ('111' ) } print ()
都输出 111,很明显 function 有变量提升
print ()var print = function ( ) { console .log ('111' ) } print ()
直接报错print is not a function
,因为一开始是var print = undefined
,不是函数
条件判断下的变量提升
console .log (a)if (false ) { var a = '111' } console .log (a)
输出是 2 个 undefined,因为:在当前作用域中不管条件是否成立都会进行变量提升
var y = 1 if (function f ( ) {}) { console .log (typeof f) y = y + typeof f } console .log (y)
很好理解,直接是未定义
console .log (a)console .log (p ())if (true ) { var a = 12 function p ( ) { console .log ('111' ) } }
题目 if (!('val' in window )) { var val = 2019 } console .log (val)console .log ('val' in window )
提升之后 window.val = undefined
重名问题下的变量提升
带 var 和 带 function 重名条件下,函数先执行变量提升
console .log (a) var a = 1 function a ( ) { console .log (1 ) }
或
console .log (a) function a ( ) { console .log (1 ) } var a = 1
输出都是函数,也就是说函数声明的变量会覆盖 var 的变量提升
var a = 1 function a ( ) { console .log (1 ) } console .log (a)
因为:
var a = undefined a = '函数' a = 1
console .log ('1' , fn ())function fn ( ) { console .log (1 ) } console .log ('2' , fn ())function fn ( ) { console .log (2 ) } console .log ('3' , fn ())var fn = '111' console .log ('4' , fn ())function fn ( ) { console .log (3 ) }
则理解为
var fn = undefined fn = '函数 1' fn = '函数 2' fn = '函数 3' fn = '111'
所以输出是:
思考题 var a = 2 function a ( ) { console .log (3 ) } console .log (typeof a)
console .log (fn) var fn = 2019 console .log (fn) function fn ( ) {}
let a = 0 , b = 0 function fn (a ) { fn = function fn2 (b ) { console .log (a, b) console .log (++a + b) } console .log ('a' , a++) } fn (1 ) fn (2 ) console .log (a, b)
函数形参的变量提升 function a (b ) { console .log (b) } a (45 )
var a = 1 function foo (a ) { console .log (a) var a console .log (a) } foo (a)
题目 var foo = '111' ;(function (f ) { console .log (foo) var foo = f || 'hello' console .log (foo) })(foo) console .log (foo)
类似的
var foo = '111' ;(function (foo ) { console .log (foo) var foo = foo || 'world' console .log (foo) })(foo) console .log (foo)
面试题
var a = 10 ;(function ( ) { console .log (a) a = 5 console .log (a) console .log (window .a ) var a = 20 console .log (a) })() var b = { a, c : b, } console .log (b.c )
非匿名自执行函数的变量提升
var a = 10 ;(function c ( ) {})() console .log (c)
var a = 10 ;(function ( ) { console .log (a) a = 20 console .log (a) })() console .log (a)
var a = 10 ;(function ( ) { console .log (a) var a = 20 console .log (a) })() console .log (a)
var a = 10 ;(function a ( ) { console .log (a) a = 20 console .log (a) })()
总结 感觉还是有点乱,这个有点难理解,面试前建议再看几遍