【JS】859- 閉包的 9 個常用場景


來源 | http://www.fly63.com/article/detial/9974?type=2


1、返回值(最常用)

  
  
  
//1.返回值 最常用的function fn() {  var name = 'hello'  return function () {    return name  }}var fnc = fn()console.log(fnc()) //hello

這個很好理解就是以閉包的形式將 name 返回。

2、函數賦值

  
  
  
var fn2function fn() {  var name = 'hello'  //將函數賦值給fn2  fn2 = function () {    return name  }}fn() //要先執行進行賦值,console.log(fn2()) //執行輸出fn2

在閉包裏面給fn2函數設置值,閉包的形式把name屬性記憶下來,執行會輸出 hello。

3、函數參數

  
  
  
function fn() {  var name = "hello";  return function callback() {    return name;  }}var fn1 = fn() //執行函數將返回值(callback函數)賦值給fn1,
function fn2(f) { //將函數作爲參數傳入 console.log(f()); //執行函數,並輸出}fn2(fn1) //執行輸出fn2

用閉包返回一個函數,把此函數作爲另一個函數的參數,在另一個函數裏面執行這個函數,最終輸出 hello

4、IIFE(自執行函數)

;(function () {  var name = 'hello'  var fn1 = function () {    return name  }  //直接在自執行函數裏面調用fn2,將fn1作爲參數傳入  fn2(fn1)})()
function fn2(f) { //將函數作爲參數傳入 console.log(f()) //執行函數,並輸出}

直接在自執行函數裏面將封裝的函數fn1傳給fn2,作爲參數調用同樣可以獲得結果 hello。

5、循環賦值

  
  
  
//每秒執行1次,分別輸出1-10for (var i = 1; i <= 10; i++) {  ;(function (j) {    //j來接收    setTimeout(function () {      console.log(j)    }, j * 1000)  })(i) //i作爲實參傳入}

如果不採用閉包的話,會有不一樣的情況。

6、getter和setter

  
  
  
function fn() {  var name = 'hello'  setName = function (n) {    name = n;  }  getName = function () {    return name;  }  //將setName,getName作爲對象的屬性返回  return {    setName: setName,    getName: getName  }}var fn1 = fn(); //返回對象,屬性setName和getName是兩個函數console.log(fn1.getName()); //getterfn1.setName('world'); //setter修改閉包裏面的nameconsole.log(fn1.getName()); //getter

第一次輸出 hello 用setter以後再輸出 world ,這樣做可以封裝成公共方法,防止不想暴露的屬性和函數暴露在外部。

7、迭代器(執行一次函數往下取一個值)

  
  
  
var arr = ['aa', 'bb', 'cc']function incre(arr) {  var i = 0  return function () {    //這個函數每次被執行都返回數組arr中 i下標對應的元素    return arr[i++] || '數組值已經遍歷完'  }}var next = incre(arr)console.log(next()) //aaconsole.log(next()) //bbconsole.log(next()) //ccconsole.log(next()) //數組值已經遍歷完

8、首次區分(相同的參數,函數不會重複執行)

  
  
  
var fn = (function () {  var arr = [] //用來緩存的數組  return function (val) {    if (arr.indexOf(val) == -1) {      //緩存中沒有則表示需要執行      arr.push(val) //將參數push到緩存數組中      console.log('函數被執行了', arr)      //這裏寫想要執行的函數    } else {      console.log('此次函數不需要執行')    }    console.log('函數調用完打印一下,方便查看已緩存的數組:', arr)  }})()fn(10)fn(10)fn(1000)fn(200)fn(1000)

執行結果如下:


可以明顯的看到首次執行的會被存起來,再次執行直接取。

9、緩存

  
  
  
//比如求和操作,如果沒有緩存,每次調用都要重複計算,採用緩存已經執行過的去查找,查找到了就直接返回,不需要重新計算
var fn = (function () { var cache = {}; //緩存對象 var calc = function (arr) { //計算函數 var sum = 0; //求和 for (var i = 0; i < arr.length; i++) { sum += arr[i]; } return sum; } return function () { var args = Array.prototype.slice.call(arguments, 0); //arguments轉換成數組 var key = args.join(","); //將args用逗號連接成字符串 var result, tSum = cache[key]; if (tSum) { //如果緩存有 console.log('從緩存中取:', cache) //打印方便查看 result = tSum; } else { //重新計算,並存入緩存同時賦值給result result = cache[key] = calc(args); console.log('存入緩存:', cache) //打印方便查看 } return result; }})();fn(1, 2, 3, 4, 5);fn(1, 2, 3, 4, 5);fn(1, 2, 3, 4, 5, 6);fn(1, 2, 3, 4, 5, 8);fn(1, 2, 3, 4, 5, 6);

輸出結果:

1. JavaScript 重溫系列(22篇全)
2. ECMAScript 重溫系列(10篇全)
3. JavaScript設計模式 重溫系列(9篇全)
4.  正則 / 框架 / 算法等 重溫系列(16篇全)
5.  Webpack4 入門(上) ||  Webpack4 入門(下)
6.  MobX 入門(上)  ||   MobX 入門(下)
7. 100 +篇原創系列彙總

回覆“加羣”與大佬們一起交流學習~

點擊“閱讀原文”查看 100+ 篇原創文章

本文分享自微信公衆號 - 前端自習課(FE-study)。
如有侵權,請聯繫 [email protected] 刪除。
本文參與“OSC源創計劃”,歡迎正在閱讀的你也加入,一起分享。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章