引入问题
问题一
<script>
function fn(){
console.log(111);
}
var a=function(){
console.log(222);
}
fn();
a();
</script>
这里在控制台会输出111,222,这里第一个是function关键字加函数名定义的函数,第二个是定义一个变量再把一个函数赋值给这个变量。
请看下面一种情况
<script>
fn();
a();
function fn(){
console.log(111);
}
var a=function(){
console.log(222);
}
</script>
结果控制台输出111,和报错信息: a is not a function
解析问题一
首先我们来了解javascript的代码运行阶段
- 预解析阶段
在预解析阶段,会把函数的定义和变量的定义提前,但是对于变量的提前,仅仅是变量的提前,而赋值是不被提前的。所以第二种方式的函数不能先调用定义。
所以,上面错误的代码,其和下面的这种代码是同一个执行顺序
<script>
function fn(){
console.log(111);
}
var a;
var b;
这上面就是我们看不到的被串改后的代码提前后的代码顺序
----------
fn();
a();
function fn(){
console.log(111);
}
var a=function(){
console.log(222);
}
var b="111";
</script>
2.执行阶段
按照代码的逻辑从上到下执行,但是也有例外。如一下函数是不符合这个规律的。
setTimeout,setInterval,ajax中的回调函数,需要出发执行的函数。
问题二
<script>
var a=function(){
console.log("qqq");
}
function fn(callback){
callback();
}
fn(a);
</script>
解析问题二
定义变量设置的函数可以当成参数进行传递,并且可以在被传的函数里面进行调用。即一个函数可以成为另一个函数的参数进行调用,并且在另一个函数中进行执行。函数的参数可以是一个函数,并且这个函数可以直接调用。
问题三
关于函数闭包
<script>
function fn4(){
var n=1;
var fn2=function(){
n++;
console.log(n);
}
return fn2;
}
var fn1=fn4();
fn1(); //2
fn1(); //3
fn1(); //4
fn1(); //5
fn1(); //6
</script>
为什么2,会变成3,变成4,变成5。。。。?
解决问题三
解析:js中重要的一个概念 闭包
闭包会保存函数内部的作用域,fn4这个函数的内部是私有空间。
还有就是通过这个案例我们可以看出,函数可以可以作为返回值,函数的嵌套形成闭包。