13. 关於 IIFE 的 4 题练习

IIFE 立即函式


定义

IIFE (Immediately Invoked Function Expression) 是在宣告完函式後马上执行的一种函式

示例

这里尝试把一般的函式呼叫,改写成匿名函式:

// original
function greeting() { console.log("Hi"); }
greeting();

// IIFE
(function () { console.log("Hi"); })();

这种形式包含

  1. 用 Grouping operator () 包起来的匿名函式(anonymous function)。
  2. 在 Grouping operator () 後用expression () 执行函式。

即使不是宣告匿名函式,也可以正常运行,只是没什麽意义:

(function greeting() { console.log("Hi"); })();
// output: "Hi"

IIFE 的用途,通常是 避免变数污染到global scope

(function () { 
    var name = "apple";
    return name;
})();

console.log(name);
// output: "" ( in browser )

→ 因为在函式内宣告的变数只有function scope,因此不会影响到全域变数。

  • 延伸问题: 为什麽保持网站的全域(global scope)原样是一个好做法?
    我想了两种可能:
    1. 基於开发者自身的立场,因为 全域变数在任何位置都可以被呼叫,会很容易造成变数混乱。 像是原本要在function里使用的一个变数,但没有定义到,结果function自己找不到变数只好往外找(scope chain),可能就会影响全域变数,那後续的程序码会全部乱掉。
    2. 基於合作的他人立场,大概是便於程序码的维护。就像使用bootstrap或其他modules时,工程师在开发网页的认知一定都是基於原始定义,如果原始定义的全域变数被修改了,会造成其他工程师在合作和维护上的不便。
      (如果有错拜托洗脸我QQ我会非常感激。)

如果把 IIFE 指派给变数,会储存回传值,不会储存 function 本身:

let hi = (function () { 
    let hi = "Hi!!";
    return hi;
})();

console.log(hi);  
// output: Hi!!

例题

  1. 解释下列程序码为什麽不是IIFE: function foo(){ }();. (Immediately Invoked Function Expression,立即函式) (题目来自 前端工程师面试问题集 ★ Front-end Job Interview Questions)
    • 需要修改那里使它成为IIFE?

Ans. 不是, function foo(){ }() → (function foo(){ })(); 在function外加上(小括号),foo可以删除。

  1. 下面的两个 alerts 的结果会是什麽?
    (题目来自 前端工程师面试问题集 ★ Front-end Job Interview Questions)
var foo = "Hello";
(function() {
  var bar = " World";
  alert(foo + bar);
})();
alert(foo + bar);

Ans. "Hello World" ; (错误讯息)ReferenceError: bar is not defined

  1. 底下程序码是否为正确呢?
    a. 出现错误
    b. 不会出现错误
    (题目来自 六角学院观念测验:JavaScript 热门面试题。)
var a = 1
(function(){console.log(a);})()  

Ans. 出现错误, 程序码没有断句,1会被当成function呼叫。
可以看成这样:

var a = 1(function(){console.log(a);})() 
// TypeError: 1 is not a function

4.请问以下立即函式会出现什麽讯息?
(题目来自 六角学院观念测验:JavaScript 热门面试题。)

(function(){
    console.log('六角学院 A'); 
}());

(function(){
    console.log('六角学院 B');
});

Ans. 六角学院 A / (){ console.log('六角学院 B'); }
第一个答案会执行,是因为符合 JSLint 的版本。
第二个答案则是只包裹了function但没有执行,所以回传了整个function。

【如内文有误还请不吝告知>< 谢谢阅览至此的各位:D】

参考资料:

-----正文结束-----

非同步请求是我的罩门,所以前几天的文章都看资料看得很痛苦。
今天写IIFE整个加速而且快乐很多。
BTW 昨天的文章有补充fetch API的部分,有兴趣可以回去看看。


<<:  [Day 01] 前言、文章大纲

>>:  [Day 14] 资料产品生命周期管理-描述型模型

Progressive Web App 推播通知: 网站推播通知用户端实作入门 (24)

什麽是网站推播通知 推播通知不管对 App 或是网站来说都是一种重新吸引用户来使用 App 的方法,...

【Day18】物件与纯值

在昨天的文章有提到物件可以使用 . 来新增属性,以下使用各种型别来新增属性 物件 物件新增属性 co...

[Day03]程序菜鸟自学C++资料结构演算法 – 常见的线性串列其一:阵列Array List

前言:先来谈谈线串列表示甚麽,线性串列就是一种a[0],a[1],a[2]…,a[n]所组成的有限序...

Vaadin Pro Components 图表初探 - day26

目标 使用 Pro Components 制作图表 萤幕截图 汇出png图 Vaadin Chart...

Android Studio初学笔记-Day27-ViewPager

ViewPager ViewPager是个让使用者能左右切换view的功能,而ViewPager是直...