IIFE(立即执行函数表达式)作用域

54 阅读2分钟

1,IIFE的函数无法进行赋值

var foo = 10; 
(function foo() { 
    console.log(foo); // [function foo] 
    
    // 内部作用域,会先去查找是已有变量foo的声明,有就直接赋值20,确实有了呀,发现了具名函数,拿此foo做赋值 
    // IIFE的函数无法进行赋值(内部机制,类似const定义的常量)所以无效 
    foo = 20; 
 
    console.log(foo); // [function foo] 
    console.log(window.foo)//10 
})()

所以严格模式下能看到错误:


// 所以严格模式下能看到错误:uncaught typeerror: assignment to constant variable
var foo = 10;
(function foo() {
    'use strict'
    console.log(foo); 
    foo = 20; // uncauth typerror: assignment to constant variable
    console.log(foo); 
    console.log(window.foo)
})()

2,

//在全局作用域中声明 `b`,并挂载到 `window` 对象上。
var b = 10;
(
    function b() {
        //`window.b = 20` 修改的是全局对象的 `b`,即覆盖了全局作用域中 `var b = 10` 的值
        window.b = 20;
        
        //在 IIFE 作用域中,`b` 指向的是IIFE 定义的具名函数。
        //在 IIFE 内部,`b` 是指向函数本身的**局部变量**,优先级高于全局作用域。
        console.log(b); //【function b】
        
        console.log(window.b) // 20;
    }
)()

3,IIFE声明了一个新的局部变量,可以与函数同名,局部变量可以遮蔽外部的全局变量

 // 使用 `var` 在全局作用域中声明了变量 `b`, 
 //`var` 声明的变量会自动挂载到 `window` 对象上:
var b = 10;  
(function b() {

// 由于是具名函数,IIFE 内部的 `b` 会指向这个函数自身(在函数体内是只读的)。
// 但在函数体内,声明了一个新的局部变量 `b`,这个新的 `b` 会遮蔽外部的`b`
    var b = 20; 
    
    console.log(b); // 20
    
    //IIFE 内部的变量声明**不会影响全局作用域的变量**。
    console.log(window.b); // 10
})();

4,var a 在函数内被提升,但未赋值,默认为 undefined

var a = 10;
(function () {
 // `var a = 20` 会在编译阶段被提升到作用域的顶部,变量声明提升,但未赋值,默认为 undefined 等于多了一行代码:var a; 然后 倒数第二行 被改成 a=20
    console.log(a) // undefined
    
    // a被赋值5
    a = 5console.log(a) // 5
    console.log(window.a) //  10
    
    //局部作用域中的 `a` 被赋值为 `20`。
    var a = 20;
    
    console.log(a) //20
})()

5,

  • 如果 IIFE 内部没有声明局部变量 a,JavaScript 就会通过作用域链去全局作用域寻找 a

  • 由于全局作用域存在 var a = 10,所以 IIFE 直接使用全局的 a

  • a = 5 就会直接修改全局 a 的值。

//如果把 var a = 20,这段去掉,那么就只能去拿外部a的值了
var a = 10;
(function () {
    console.log(a) // 10
    a = 5
    console.log(a) // 5
    
    //因为 `a = 5` 修改了全局的 `a`,所以 `window.a` 现在是 `5`。
    console.log(window.a) //  5
})()