函数声明的提升
<script>
// 函数声明
console.log(le()); //声明式
function le(str) {
return str = '声明式'
}
console.log(le()); //声明式
// 函数表达式
console.log(Le()) //error 错误 34.html:19 Uncaught TypeError: Le is not a function
var Le = function Le(str) {
return str = '表达式'
}
console.log(Le('b'))//表达式
// 上面代码等同于
// ⬇ ⬇ ⬇ ⬇ ⬇
// ⬇ ⬇ ⬇ ⬇ ⬇
// ⬇ ⬇ ⬇ ⬇ ⬇
// ⬇ ⬇ ⬇ ⬇ ⬇
var Le;
console.log(Le('a'));
Le = function (str) {
return str = '表达式'
}
console.log(Le('b'))//表达式
// 用函数声明创建的函数le可以在le定义之前就进行调用;
// 而用函数表达式创建的Le函数不能在Le被赋值之前进行调用。
// 用函数声明创建的函数可以在函数解析后调用(解析时进行等逻辑处理);
// 而用函数表达式创建的函数是在运行时进行赋值,且要等到表达式赋值完成后才能调用。
// 这个区别看似微小,但在某些情况下确实是一个难以发现的陷阱。出现这个陷阱的本质原因体现在这两种类型在Javascript
// function hoisting(函数提升)和运行时机(解析时/运行时)上的差异。
var sayHello;
console.log(typeof (sayHey));//=>function
console.log(typeof (sayHo));//=>undefined
if (true) {
function sayHey() {
console.log("sayHey");
}
sayHello = function sayHo() {
console.log("sayHello");
}
} else {
function sayHey() {
console.log("sayHey2");
}
sayHello = function sayHo() {
console.log("sayHello2");
}
}
sayHey();// => sayHey2
sayHello();// => sayHello
// 上面代码等同于
// ⬇ ⬇ ⬇ ⬇ ⬇
// ⬇ ⬇ ⬇ ⬇ ⬇
// ⬇ ⬇ ⬇ ⬇ ⬇
// ⬇ ⬇ ⬇ ⬇ ⬇
// sayHey是用函数声明创建的,在JS解析时JS编译器将函数定义进行了函数提升,
// 也就是说,在解析JS代码的时候,JS编译器(条件判断不形成新的作用域,
// 两个sayHey函数定义都被提升到条件判断之外)检测到作用域内有两个同名的sayHey定义,
// 第一个定义先被提升,第二个定义接着被提升(第二个定义在第一个定义之下),
// 第二个定义覆盖了第一个sayHey定义,所以sayHey()输出sayHey2;
// 而sayHello是用函数表达式创建的,
// 其表达式的内容是在JS运行时(不是解析时)才能确定(这里条件判断就起到作用了),
// 所以sayHello表达式执行了第一个函数定义并赋值,则sayHello()输出sayHello。
var sayHello;
function sayHey() {
console.log("sayHey");
}
function sayHey() {
console.log("sayHey2");
}
console.log(typeof (sayHey));//=>function
console.log(typeof (sayHo));//=>undefined
if (true) {
//hoisting...
sayHello = function sayHo() {
console.log("sayHello");
}
} else {
//hoisting...
sayHello = function sayHo() {
console.log("sayHello2");
}
}
sayHey();// => sayHey2
sayHello();// => sayHello
// 总结:
// Javascript 中函数声明和函数表达式是存在区别的,函数声明在JS解析时进行函数提升,
// 因此在同一个作用域内,不管函数声明在哪里定义,该函数都可以进行调用。
// 而函数表达式的值是在JS运行时确定,并且在表达式赋值完成后,该函数才能调用。
// 这个微小的区别,可能会导致JS代码出现意想不到的bug,让你陷入莫名的陷阱中。
// **函数声明才会提升,函数表达式是属于变量提升**
</script>