函数声明有三种:function a()、函数表达式以及 Function构造函数。前两种最为常见,用的最多。函数
(1)function 命令ui
function foo(s){
console.log(s);
}
复制代码
(2)函数表达式spa
var f = function(s){
console.log(s);
}
复制代码
函数表达式后面通常是匿名函数,但也能够是具名,若是加上函数名,则只对函数内部有效,对外部无效。意思就是在相似递归这样函数本身调用本身时有效,而在外部调用就不能经过函数名调用。code
var f = function a(){
console.log(typeof a);
};
a()// ReferenceError: x is not defined
f()// function
复制代码
在外部经过变量名调用。递归
其实js在编译过程当中表达式是分两步的,先是声明,再是赋值。例如 var a = 2作用域
总结:只有声明会被提高,而赋值或其余运行逻辑会留在原地。 也就是说,声明和赋值是在不一样的阶段,声明 var a是在编译阶段,被提高到了所在做用域的最顶端;而赋值 a = 2是在执行阶段,被留在原地等待执行。编译器
foo()
function foo(){
console.log(2)
}
//2
复制代码
foo()
var foo = function(){
console.log(2)
}
//Uncaught TypeError: foo is not a function
复制代码
因此,function 声明的函数整个就是一个声明,编译时会被提高到最顶端,因此调用时在它声明以前也能够调用;而函数表达式则只提高左边声明部分,而右边函数体被留在原地,若是在其前面调用函数,则会报错。it
若是一个函数被重复声明,后面的声明会覆盖前面的。 可是有几种状况须要注意:io
1. 都是用 function声明console
function a(){
console.log(1);
}
a() //2
function a(){
console.log(2);
}
a() //2
复制代码
因为“提高”,不管函数在哪调用都会调用后面的那一个,而前面的会被覆盖。
2. function声明又有函数表达式
var a = function(){
console.log(1);
}
function a(){
console.log(2);
}
a() //1
||
||至关于
||
var a
function a(){
console.log(2);
}
a = function(){
console.log(1);
}
a()
复制代码
2的第一种状况,这时被“提高”的是第一个函数表达式的 var a 和 第二个函数function a()。而第一个函数表达式的右边部分被留在原地,这就覆盖了被提高的第二个函数function a()。因此调用时,执行的是第一个函数表达式。
function a(){
console.log(1);
}
a() //1
var a = function(){
console.log(2);
}
||
||至关于
||
function a(){
console.log(1);
}
var a
a()
a = function(){
console.log(2);
}
复制代码
2的第二种状况,就是在调用 a()时,第二个函数表达式的右边部分被留在它的后面,因此执行第一个function a()。