这篇文章用来解答上篇面试题的问题:
具名的立即执行函数的赋值问题
在 JS 中,有两种方式来创造一个函数:
1. 函数声明
2. 函数表达式
一、函数声明
function foo() {
console.log('I am a function!')
}
以上这种写法就是函数声明。
1.1 基本原理
其中,function 是一个关键字。当它作为开头,解析器便会知道这是一个函数声明。
在执行这段代码时,会在全局作用域创建一个变量 foo,值为这个函数,且声明和赋值都会提升
所以直接可以直接打印 foo:
console.log(foo)
function foo() {
console.log('I am a function!')
}
1.2 注意事项
需要注意的是,使用函数声明的写法,必须带上函数名,否则会报错:
二、函数表达式
var foo = function() {
console.log('I am a function!')
}
以上这种写法就是函数表达式。
2.1 基本原理
在执行这段代码时,会先声明一个变量 foo,后对这个变量进行赋值。这种写法中,只有声明会被提升,赋值并不会:
console.log(foo)
var foo = function() {
console.log('I am a function!')
}
2.2 注意事项
需要注意的是,在函数表达式的写法中,还可以为函数再赋一个名称:
var foo = function bar() {
console.log('I am a function!')
}
console.log(foo)
console.log(bar)
如上面的代码,在关键字 function 后面,还有一个名字 bar。
然而,与 foo 不同,bar 并不在全局上下文中,而是在这个函数的函数作用域中,所以无法在全局作用域读取,上面代码的执行结果是:
另外还需注意一点:bar 是常量命名,也就是说,它不能被再次赋值。在严格模式下,会直接报错,在非严格模式下,赋值会静默失败:
var foo = function bar() {
bar = 10
console.log(bar)
}
foo()
这个执行结果说明:
1. bar 可以在函数作用域内获取到
2. bar = 10
这个赋值语句失效了,打印出的还是函数