成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

深入理解立即執行函數

開發 前端
立即執行函數常用于第三方庫,它可以用來隔離變量作用域,很多第三方庫都會存在大量的變量和函數,在ES5環境下為了避免變量污染,開發者想到的解決辦法就是使用立即執行函數。

[[394531]]

本文轉載自微信公眾號「神奇的程序員k」,作者神奇的程序員k。轉載本文請聯系神奇的程序員k公眾號。神奇的程序員K  

 前言

立即執行函數常用于第三方庫,它可以用來隔離變量作用域,很多第三方庫都會存在大量的變量和函數,在ES5環境下為了避免變量污染,開發者想到的解決辦法就是使用立即執行函數。

本文就跟大家分享下立即執行函數的相關知識點,歡迎各位感興趣的開發者閱讀本文。

概念介紹

立即調用的匿名函數又被稱作立即調用的函數表達式(IIFE),它類似于函數聲明,但由于被包含在括號中,所以會被解釋為函數表達式。緊跟在第一組括號后面的第二組括號會立即調用前面的函數表達式,位于IIFE中的代碼在其外部是無法訪問的。

我們舉個例子來說明下:

  1. (function() { 
  2.   // 塊級作用域 
  3.   for (var i = 0; i < 5; i++) { 
  4.     console.log(i); 
  5.   } 
  6. })(); 
  7. console.log(i); 

上述代碼中當解析到console.log(i);時,會報錯ReferenceError: i is not defined,這是因為它訪問的變量是在IIFE內部定義的,在外部訪問不到。

在es5以前,為了防止變量定義外泄,IIFE是個非常有效的方式,這樣也不會導致閉包相關的內存問題,因為不存在對這個匿名函數的引用。因此,只要函數執行完畢,其作用域鏈就可以被銷毀。

IIFE的全稱為Immediately Invoked Function Expression,翻譯過來就是立即調用函數表達式。

模擬塊級作用域

使用IIFE可以模擬塊級作用域,即在一個函數表達式內部聲明變量,然后立即調用這個函數,這樣位于函數體作用域的變量就像是在塊級作用域中一樣(如上述例子所示)。

在ES6以后,新增了塊級作用域的概念,因此我們想實現同樣的效果,就無需再使用IIFE了,我們用let來重寫下上面的例子,代碼如下所示:

  1. for (let i = 0; i < 5; i++) { 
  2.   console.log(i); 
  3. console.log(i); 

有關變量作用域的更多知識點請移步我的另一篇文章:深入理解作用域和閉包

塊級作用域無法替代立即調用函數的表達式,當你的代碼在不支持ES6+的瀏覽器上運行時,你不得不求助立即執行函數來模擬。

實現私有變量

IIFE可以返回一個函數引用,當這個函數在IIFE的詞法范圍外執行,也會創建一個閉包,使函數能夠訪問局部變量。

我們舉個例子來說明下,如下所示:

  1. const getOrderId = (function() { 
  2.   let count = 0; 
  3.   return function() { 
  4.     ++count
  5.     return `id_${count}`; 
  6.   }; 
  7. })(); 
  8. console.log(getOrderId()); 
  9. console.log(getOrderId()); 
  10. console.log(getOrderId()); 
  11. console.log(getOrderId()); 

上述代碼中:

  • 創建了一個自執行函數,其返回一個函數引用
  • 自執行函數內部有一個變量count,它就是一個私有變量,外部無法訪問
  • 最后,返回一個函數引用,形成閉包結構,對count自增后與_id進行拼接并返回

在IIFE之外無法訪問函數內部的count變量,除了從IIFE中返回的函數,別處無法讀寫該變量,這樣就能創建真正的私有狀態變量。

變量重命名

在平常開發中可能遇到兩個不同的庫,他們暴露的全局變量名卻是相同的,例如:正在使用Jquery,另一個庫也指定了一個名為$的全局變量。

為了解決命名沖突問題,可以將一段代碼封裝在一個IIFE中,將一個全局變量(比如Jquery)作為參數傳入IIFE,在函數內部,就可以以一個任意的參數名(比如 $)來訪問該參數值,我們舉個例子來說明下,如下所示:

  1. window.$ = function somethingElse() { 
  2.  
  3.     // 其他代碼 
  4.  
  5. }; 
  6.  
  7.   
  8.  
  9. (function($) { 
  10.  
  11.     // 其他代碼 
  12.  
  13. })(jQuery); 

不管在全局作用域有什么值指定給,在IIFE中,這些值都會被屏蔽,`參數一直指向Jquery方法。

捕獲全局對象

JavaScript代碼在不同環境執行時,所使用的全局對象是不同的,當代碼在瀏覽器環境運行時,全局對象是window,但是在node環境下,全局對象則是global。

在寫通用js代碼時,就可以利用IIFE將其包裝起來,例如:

  1. (function(global) { 
  2.  
  3.     // 其他代碼 
  4.  
  5. })(this); 

包裝之后,在IIFE內部使用global時在瀏覽器環境下其值就是window,node環境下其值就是global。

IIFE的兩種寫法

立即執行函數有兩種寫法:

  • (function(){})() 匿名函數包裹在一個括號運算符中,后面再跟一個小括號
  • (function(){}()) 匿名函數后面跟一個小括號,然后整個包裹在一個括號運算符中

上述兩種寫法是等價的,要想立即執行函數做到立即執行,要注意兩點:

  • 函數體后面要有小括號
  • 函數體必須是函數表達式而不能是函數聲明

函數的聲明方式

在講它們兩者之間的區別之前,我們先來了解下js函數的兩種聲明方式:表達式和聲明式。

函數的聲明式寫法為:function test(){},這種寫法會導致函數提升,所有通過function關鍵字聲明的變量都會被解釋器優先編譯,不管聲明在什么位置都可以調用它,但是它本身并不會被執行。

  1. test(); // 測試 
  2. function test() { 
  3.   console.log("測試"); 
  4. test(); // 測試 

函數的表達式寫法為:var test = function(){},這種寫法不會導致函數提升,必須先聲明后調用,不然就會報錯。

  1. test(); // 報錯:TypeError: test is not a function 
  2. var test = function() { 
  3.   console.log("測試"); 
  4. }; 

二者的區別

現在,我們回到正題,函數表達式加上()可以被直接調用,但是把整個聲明式函數用()包起來的話,則會被編譯器認為是函數表達式,從而可以用()來直接調用,如(function test(){})()。

如果將括號加在聲明式函數后面如function test(){},運行之后會報錯,因為不符合js的語法,想讓其通過瀏覽器的語法檢查,就必須添加符號,比如:()、+、!等,如下所示:

  1. function test(){ 
  2.   console.log("測試"); 
  3. }(); // 報錯 SyntaxError: Unexpected token ')' 
  4.  
  5. +function test() { 
  6.   console.log("測試"); 
  7. }(); // 正常執行 
  8.  
  9. -function test() { 
  10.   console.log("測試"); 
  11. }(); // 正常執行 
  12.  
  13. !function test() { 
  14.   console.log("測試"); 
  15. }();  // 正常執行 
  16.  
  17. ~function test() { 
  18.   console.log("測試"); 
  19. }();  // 正常執行 
  20.  
  21. void function test() { 
  22.   console.log("測試"); 
  23. }();  // 正常執行 
  24.  
  25. new function test() { 
  26.   console.log("測試"); 
  27. }();  // 正常執行 

立即執行函數一般也寫成匿名函數,使用function關鍵字聲明一個函數,但未給函數命名,通過這種方式聲明的函數就是匿名函數,例如function(){}。

匿名函數不能單獨使用,否則會js語法報錯,需要用()包起來,當我們需要給匿名函數傳值時,寫在其后面的括號即可,例如:

  1. (function(val) { 
  2.   console.log(val); 
  3. }("我是匿名函數的參數")); 

講解到此處時,我們會發現,上述代碼的寫法正好是立即執行函數的第二種寫法??,我們知道函數體后面跟著小括號,這個函數就會立即執行。

我們知道自執行函數是需要用()將其包裹起來的,前面我們講到用()包裹起來的代碼,編譯器會認定它為函數表達式,因此可以在其后面加個()立即調用這個函數。同時也可以從這個括號來為匿名函數傳參,代碼如下所示:

  1. (function(val) { 
  2.   console.log(val); 
  3. })("我是自執行匿名函數"); 

我們發現上述代碼的寫法正好是立即執行函數的第一種寫法??

寫在最后

至此,文章就分享完畢了。

責任編輯:武曉燕 來源: 神奇的程序員K
相關推薦

2021-09-26 09:59:14

MYSQL開發數據庫

2019-11-05 10:03:08

callback回調函數javascript

2021-10-16 17:53:35

Go函數編程

2020-07-24 10:00:00

JavaScript執行上下文前端

2016-12-08 15:36:59

HashMap數據結構hash函數

2010-06-01 15:25:27

JavaCLASSPATH

2020-07-21 08:26:08

SpringSecurity過濾器

2020-12-16 09:47:01

JavaScript箭頭函數開發

2009-11-18 12:38:04

PHP字符串函數

2010-06-28 10:12:01

PHP匿名函數

2023-10-19 11:12:15

Netty代碼

2021-02-17 11:25:33

前端JavaScriptthis

2009-09-25 09:14:35

Hibernate日志

2013-09-22 14:57:19

AtWood

2020-09-23 10:00:26

Redis數據庫命令

2019-06-25 10:32:19

UDP編程通信

2025-05-06 00:43:00

MySQL日志文件MIXED 3

2017-08-15 13:05:58

Serverless架構開發運維

2025-06-05 05:51:33

2024-02-21 21:14:20

編程語言開發Golang
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 久久国产精品-国产精品 | 午夜精品久久久久久久久久久久久 | 色999日韩| 亚洲综合日韩精品欧美综合区 | 欧美精三区欧美精三区 | 人操人人 | 亚洲国产福利视频 | 久久久久久国产精品 | 91电影在线 | 亚洲欧洲成人在线 | 成人a免费 | 婷婷综合五月天 | www.久久.com | 天天插天天干 | 日韩免费看视频 | 色在线视频网站 | aa级毛片毛片免费观看久 | 国产成人网 | 一区二区三区四区五区在线视频 | 久久久久久久久久久91 | 中文字幕 视频一区 | 欧美一级www片免费观看 | 日日骚av | 精品久久免费 | 操久久 | 男女在线网站 | 久久久久久久一区二区三区 | 亚洲最大看片网站 | 精品国产欧美一区二区三区成人 | 国产日韩精品视频 | 欧美在线a | 一本久久a久久精品亚洲 | 成人精品一区 | 国产九九九九 | 中文字幕亚洲欧美日韩在线不卡 | 亚洲成人日韩 | 国产成人av在线播放 | 亚洲激情综合网 | 精品视频一区二区三区在线观看 | 一区二区在线免费观看 | 亚洲成人第一页 |