前言
是不是经常遇到面试问你,为什么会变量提升,函数提升,它的行为又是什么?
解答
js程序编译有两个步骤:
- 预解析 (就是执行上下文,有三类变量声明,函数声明和this,本文暂不讨论this,后续专门写)
- 代码执行
demo
var a = 1;
function a() {}
a = 2;
如上述demo中,其实真正解析成:
var a; // 第一步
a = function () {} // 第二步
a = 1; // 第三步
a = 2; // 第四步
第一步,变量声明提升a;第二步,函数提升,把函数赋值给a;第三步变量赋值a=1;第四步变量赋值a=2。
:编译器对代码进行预解析,先将变量声明提升,再将函数提升,接下来就是引擎进行变量赋值。(记住,变量提升只是声明提升,赋值不提升,函数提升将提升到赋值之前。)
隐式变量分配权重大
demo
function parent(a) {
var b = 2;
function a() {return 'a'}
function b() {return 'b'}
b = 3;
return a + b;
}
console.log(parent(1)); // function a() {return 'a'} 3
大家看到这个答案是不是很疑惑,不应该函数先提升,赋值后运行吗?为何return a +b 得到的是函数a + 3呢?
解析上述demo:
function parent() {
var a;
var b;
a = 1;
a = function() {return "a";};
b = function() {return "b";};
b = 2;
b = 3;
return a + b;
}
console.log(parent()); // function a() {return 'a'}3
隐式变量分配在函数提升之前,所谓隐式变量分配在这里就是函数传递过来的值1。
:编译器对代码进行预解析,先将变量声明提升,隐式变量分配提升(函数传值),再将函数声明提升,接下来就是js引擎让代码逐步执行。
给大家出两道题:
一、为何第一个num是undefined
var num = 123;
function foo1(){
console.log( num ); //undefined
var num = 456;
console.log( num ); //456
}
foo1();
提示:foo1函数提升了。
二、为何打印1
foo(); // 1
var foo;
function foo() { console.log( 1 );
}
foo = function() { console.log( 2 );
}
需要注意的是,遇到匿名函数(函数表达式)当成普通变量来处理,不要当成函数声明。
更多内容可以看我的集录: 全面攻陷js:更新中...
网友评论