477 函数声明,命名函数表达式

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
    })();

posted on 2020-06-21 10:07  冲啊!  阅读(237)  评论(0编辑  收藏  举报

导航