var b = 10;
// 匿名函数具名化、命名函数表达式
(function b() {
b = 20;
console.log(b); // 函数b自己
})();
console.log(b); // 10
解析:
【这里的】立即执行函数b属于NFE(命名函数表达式),NFE的性质就是可以在内部访问标识符,但是无法修改标识符的指向。
标识符对函数来说是一个常量,无法修改,这个赋值静默失败,意思是20的赋值对它没用,但是可以打印。
函数表达式与函数声明不同,函数名只在该函数内部有效,并且此绑定是常量绑定。
对于一个常量进行赋值,在 strict 模式下会报错,非 strict 模式下静默失败。
IIFE中的函数是函数表达式,而不是函数声明。
函数声明
以下说的 只考虑ES5 不考虑ES6的class
函数定义方式之一:
函数声明 / function declaration
要求在[语句]的[开头] 必须是 function 关键字
如果function前面有任何操作符 包括分组操作符即圆括号 【操作符还有+ - * / % ! || && 等】 那么这个函数都不是函数声明 而是函数表达式
函数声明 会产生作用域提升
函数表达式 则不会影响外部作用域
这个例子中的函数a 没有执行 但是执行或不执行 都不会影响这个。
【括号()的作用是形成一个表达式,如果不写括号(),相当于只定义了一个函数,并没有形成一个函数表达式。所以要先用括号(),让它形成表达式】
一个是函数声明 一个是函数表达式结合普通的var
甚至可以不用圆括号 用任何一元操作符拼在前面都可以让它成为函数表达式(function expression) 立即执行函数表达式 IIFE 就是指这样
为什么第一个有语法错误呢
是因为 如果[语句]以function[开头] 解析器就期望它必须是函数声明
而函数声明不能缺省名字
所以语法错误
只要function不出现在语句开头 就是表达式 就不要求必须有名字
其实第一个函数a没有执行 第一个a是函数声明
函数声明 自己单独构成一个语句
函数声明的花括号结束时 这个语句就结束了
看第4个 注意分号 第4个和第一个等价 这就是 "函数声明自己单独构成一个语句"的意思
圆括号有歧义性:
作为操作符 有两个意思
函数执行符 和 分组操作符
第一个 第三四个 都是分组符 解析器怎么去理解歧义 完全就是按照上下文和死规则解析出确定的结果
变体
var b = 10;
(function b() {
b = 20;
console.log(b); // 函数b
})();
(function b() {
var b = 20; // 【用var声明一个新的变量b,不是修改原来的变量b。】
console.log(b); // 20
})();
(function b() {
// 【用var声明一个新的变量b,不是修改原来的变量b,加上变量声明提升。】
console.log(b); // undefined
var b = 20;
})();
(function () {
// 匿名函数,函数没有名字
b = 20;
console.log(b); // 20
})();