预编译 运行过程
通篇的检查是否有语法错误,有则直接抛错,不执行任何语句
预编译
解释一行,执行一行
变量提升
变量只把声明提升,赋值不提升
函数
函数声明:整体提升
函数表达式:只提升变量,字面量不提升
1 2 3 4 5 6 7 test(); function test ( ) { console .log(1 ); } console .log(a); var a;
暗示全局变量 imply global variable
没有声明(没写var)就赋值的变量
全局声明或者不声明(没写var)得变量都会挂在 window 上
1 2 3 4 5 6 7 8 9 function test ( ) { var a = b = 1 ; } test(); console .log(b); console .log(window .b); console .log(a); console .log(window .a);
🌈AO(activation object)活跃对象,函数上下文
寻找形参和变量声明 (没用var声明的变量不提升变量名,不声明var的变量被修改,当前作用域有此变量的,优先修改此作用域内的变量 )
实参值赋值给形参
寻找函数声明并赋值
执行
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 function test (a ) { console .log(a); var a = 1 ; console .log(a); function a ( ) {} console .log(a); var b = function ( ) {} console .log(b); function d ( ) {} } test(2 ); AO = { a: undefined -> 2 ->, function a ( ) {} -> 1 , b: undefined -> function ( ) {}, d: function d ( ) {} }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 function test (a, b ) { console .log(a); c = 0 ; var c; a = 5 ; b = 6 ; console .log(b); function b ( ) {} function d ( ) {} console .log(b); } test(1 , 2 ); AO = { a: undefined -> 1 -> 5 , b: undefined -> 2 -> function b ( ) {} -> 6 , c: undefined -> 0 , d: function d ( ) {} }
1 2 3 4 5 6 7 8 9 10 11 console .log(a);a = 2 ; console .log(a);var a = 2 ;
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 function test ( ) { console .log(a); a = 2 ; } test(); function test ( ) { console .log(a); var a = 2 ; } test();
代码块、if 语句中,通过 var 声明的变量,会提升到外层作用域(也就是里外共享var声明的变量)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 console .log(a);if (true ) { a = 2 ; } console .log(a);if (true ) { var a = 2 ; } var a = 1 ;{ a = 3 ; console .log(a); var a; } console .log(a);
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 function test ( ) { console .log(a); if (true ) { a = 2 ; } } test(); function test ( ) { console .log(a); if (true ) { var a = 2 ; } } test();
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 { a = 3 ; } console .log(a); { var a = 3 ; } console .log(a); if (true ) { a = 3 ; } console .log(a); if (false ) { a = 3 ; } console .log(a); if (true ) { var a = 3 ; } console .log(a); if (false ) { var a = 3 ; } console .log(a);
GO(global object)全局上下文
寻找变量
寻找函数声明
执行
GO === window
1 2 3 4 5 6 7 8 9 10 11 12 13 var a = 1 ;function a ( ) { console .log(2 ); } console .log(a);GO = { a: undefiend -> function a ( ) {} -> 1 }
1 2 3 4 5 6 7 8 9 console .log(a, b);function a ( ) {}var b = function ( ) {}; GO = { b: undefined , a: function a ( ) {} }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 function test ( ) { var a = b = 1 ; console .log(a); } test(); GO = { b: 1 } AO = { a: undefined -> 1 }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 var b = 3 ;console .log(a);function a (a ) { console .log(a); var a = 2 ; console .log(a); function a ( ) {} var b = 5 ; console .log(b); } a(1 ); GO = { b: 3 a: function a ( ) {} } AO = { a: undefined -> 1 -> function a ( ) {} -> 2 , b: undefined -> 5 } AO = { b: undefined -> 5 }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 a = 1 ; function test ( ) { console .log(a); a = 2 ; console .log(a); var a = 3 ; console .log(a); } test(); GO = { a: undefined -> 1 , test: function test ( ) {} } AO = { a: undefined -> 2 -> 3 }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 function test ( ) { console .log(b); if (a) { var b = 2 ; } c = 3 ; console .log(c); } var a;test(); a = 1 ; console .log(a);GO = { test: function test ( ) {}, a: undefined -> 1 , c: 3 } AO = { b: undefined }
🌈 if代码块陷进 假定 if 中有一个函数声明 function a() {}
if 未执行时:
if 里的函数声明首先把变量名 a **提升到 当前作用域(不是块作用域)的 最顶部** a = undefined
if 执行时:
函数声明整体 会被提升到块作用域顶部
执行到函数声明语句时,会把块作用域里的 a 赋值到当前作用域 同名变量 a
1 2 3 4 5 6 7 8 9 10 11 console .log(b);if (true ) { console .log(b); function b ( ) {} }
1 2 3 4 5 6 7 8 9 var f = function ( ) {return true ;};var g = function ( ) {return false ;};(function ( ) { console .log(g); if (g() && [] == ![]) { f = function f ( ) {return false ;}; function g ( ) {return true ;}; } })();
分析:
if代码块中的 var 变量会提升,但函数声明并不会整体提升,而只会提升函数名到当前作用于顶端。
赋值的执行一定会在if执行的过程中做。
上面打断点会发现,function g的g变量是提升到if外边了,但此刻还是undefined。而iife外边的f,g此刻在iife中是可以访问的。但由于iife中有了同名g,所以还是undefined,然后if判断是g()由于g是undefined不是函数所以报错了。另外if中的f前面由于没有var ,所以改的是iife外边的f
练习 1 2 3 4 5 6 7 function test ( ) { return a; a = 1 ; function a ( ) {} var a = 2 ; } console .log(test());
1 2 3 4 5 6 7 function test ( ) { a = 1 ; function a ( ) {} var a = 2 ; return a; } console .log(test());
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 a = 1 ; function test (e ) { function e ( ) {} arguments [0 ] = 2 ; console .log(e); if (a) { var b = 3 ; } var c; a = 4 ; var a; console .log(b); f = 5 ; console .log(c); console .log(a); } var a;test(1 ); go = { a: undefined -> 1 , test: function test ( ) {}, f: undefined -> 5 } ao = { a: undefined -> 4 , b: undefined , c: undefined , e: undefined -> 1 -> function e ( ) {} -> 2 }
面试题 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 var a = false + 1 ;console .log(a); var b = false == 1 ;console .log(b); if (typeof (a) && (-true ) + (+ undefined ) + '' ) { console .log('通过' ); } else { console .log('未通过' ); } if (1 + 5 * '3' === 16 ) { console .log('通过' ); } else { consoel.log('未通过' ); } 🍒 console .log(!!' ' + !!'' - !!false || '通过了' ); window .a || (window .a = '1' );console .log(window .a);
1 2 3 4 5 6 7 8 function test ( ) { console .log(a); if (false ) { function a ( ) {} } } test(); console .log(a);
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 var a = 0 ;console .log('No.1' , a);{ console .log('No.2' , a); a = 1 ; console .log('No.3' , a); function a ( ) {} console .log('No.4' , a); a = 2 ; console .log('No.5' , a); } console .log('No.6' , a);
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 let a = 0 ;console .log(a);if (true ) { a = 1 ; console .log(a); function a ( ) {} a = 2 ; console .log(a); } console .log(a);
1 2 3 4 5 6 { let a = 1 ; function a ( ) {} }