匿名函數、嵌套函數、閉包是怎麼回事?

来源:http://www.cnblogs.com/Beck-Z/archive/2017/10/20/7699687.html
-Advertisement-
Play Games

匿名函數: 之前的文章也有講到,指的是 沒有函數名的函數 嵌套函數呢 ? 請看代碼: 如代碼所示,函數內部嵌入函數,稱之為嵌套函數。 那閉包又是什麼呢? 不多說,看代碼 這麼看,感覺像是,只要是嵌套函數,且能訪問上一層作用域的變數就是閉包。 是這樣嗎? 我們知道,js中,分為全局作用域,局部作用域, ...


匿名函數: 之前的文章也有講到,指的是 沒有函數名的函數

1 function (){ console.log('匿名函數') }

嵌套函數呢 ?  請看代碼:

1 function test (){
2    var  sum = 20;
3    //內嵌函數
4    demo = function(){
5         alert(sum);
6         console.log('我是嵌套函數');
7     }
8 }    

如代碼所示,函數內部嵌入函數,稱之為嵌套函數。

那閉包又是什麼呢?  

不多說,看代碼

 1 function demo(){
 2    var num = 0;
 3    
 4    // 返回一個函數 
 5    return function(){
 6       alert( num+1 );
 7    }
 8 
 9 } 
10 //將返回的函數賦值給 add 變數
11 var add = demo();
12 // add就是一個閉包
13 add();

這麼看,感覺像是,只要是嵌套函數,且能訪問上一層作用域的變數就是閉包。 是這樣嗎?

我們知道,js中,分為全局作用域,局部作用域,每個函數也就相等於一個局部作用域。

同理,變數,也分為全局變數和局部變數。 有什麼區別呢?

在瀏覽器中,全局作用域對象是 window,也就是說頁面一打開,window對象就存在。

在js中,每個函數是局部作用域,局部變數會隨著 函數的執行創建和執行完畢後銷毀。

而全局變數,只要頁面不關閉,則會一直存在。並不會隨著函數的執行完畢而銷毀。

那麼和閉包有什麼關係呢? 

在 “javaScript高級程式” 這本書有講到過“作用域鏈”的概念, 特殊之處,在於函數內部可以直接讀取全局變數。

而函數外部卻不能讀取函數內部的變數。

也就是說,作用域鏈就像只能往上不能往下的階梯。我們看段代碼理解

1 var  name = "window";
2 var  age    =  20;
3 dmeo();
4 function demo(){
5      var age = 21;
6      console.log(name);  // window
7      console.log(age);     //21
8 }

在執行 demo() 函數時,就會創建一個通往全局作用域鏈,保存著當前作用域的變數,以便查找返回。

在執行 console.log( name ) 這段代碼時,會搜尋當前作用域( demo函數 ) 中是否存在 name 變數,因當前作用域不存在,所以在往上找到全局變數 name ,因此返回 window;

在執行 console.log( age ) 這段代碼時, 也會搜尋 當前作用域(demo函數) 中是否存在 age 變數,因為存在,所以返回 21。

既然機制是只能往上讀, 那麼考慮一個問題,怎麼在外部讀取內部函數的變數呢?

辦法不是沒有,稍微變通下即可。這就需要用到閉包的概念,

 1 function  f1(){
 2    var num = 0 ;
 3    //定義內部函數
 4    function f2(){
 5       return  num + 1;
 6    }
 7    //返回 f2函數引用
 8    retufn  f2;
 9 }
10 
11 // bar 變數也指向 f2 函數,在此也是一個閉包
12 var bar = f1();
13 
14 //執行
15 bar();   // 1;

我們知道,函數中的變數會隨著函數的執行完畢後會被銷毀。而如上代碼,f1()函數執行完畢後,將f2函數賦值給一個全局變數,而f2函數的變數又依賴f1的num變數,因此,f1

中的num變數並不會隨著f1的函數執行完畢後而銷毀。

這裡借用 “阮一峰” 大神的題目藉此解析加深理解。

鏈接: 學習javaScript閉包

 1 var name = "the window";
 2   
 3  var obj = {
 4       name : 'the obj',
 5       getName : function(){
 6           return funciton(){ 
 7                return this.name;
 8           }
 9       }
10 }
11 
12 //執行 getName返回的函數
13 alert(obj.getName()());

 我們看調用函數分析, 分成兩部分執行。 先來看 obj.getName();  此時getName函數由 obj對象調用,因此this的值是 obj。 但此時並不是輸出而是返回一個函數。

再加上一個(); 執行返回的函數,但此時返回的函數並沒有任何對象調用,當不是對象本身調用,this的值會被提升到 window對象。因此輸出的是 “the window" 

var name = "the Window";

var obj = {
    name : "the obj",
    getName : funciton(){
        var that = this;
        return function(){
             return that.name;
         }
    }
}

//執行 getName 返回的函數
alert(obj.getName()());

看了上面的題目,這個應該 小意思吧, 你說呢 ?

 


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 移動端前端開發較PC端開發最大的不同之一就是需要適配各種大小不同的屏幕尺寸,如何實現辛苦編寫的 H5 頁面在各個機型屏幕上都能得到最佳展示?設計師設計的視覺稿為什麼都是2倍稿? ...
  • 此次的亮點不是three.js的3d部分,而是通過調用攝像頭然後通過攝像頭的圖像變化進行簡單的判斷後進行一些操作。上篇中我通過簡單的示例分析來學習three.js,這次是通過上一篇的一些代碼來與攝像頭判斷部分的代碼相互結合,弄一個新的東西,可以看下圖 說明 這次的示例是我們可以通過一個攝像頭隔空控制 ...
  • 項目中之前需要分頁插件,以前用的都是單純叫做pagenation.js的插件,但是這次集成的時候,項目組一個孩紙用了這個插件,結合網上的例子琢磨了一把。其實大致流程都是相同的,主要將我在用這個分頁插件的一些心得分享出來: 1、分頁插件引入html中需要: bootstrap.css 分頁插件js 自 ...
  • Ionic--構建APP側邊欄 底部選項卡 輪播圖 載入動畫;最近正在學習手機移動端,本文就Ionic的使用,簡單示例了一些樣式。 ...
  • jquery插件一般是這麼乾的: $.fn.插件名稱 = function(){}, 把插件的名稱加在.fn上,在源碼裡面實際上是擴展到構造函數的原型對象上,如果你沒看過jquery的源代碼,或者你曾經看過,但是不知道為什麼把插件擴展到fn上,那麼本篇文章就能解答你的疑惑。關於jquery插件開發方 ...
  • 同一個頁面中有許多地方都用到了單選按鈕並設置了預設選中 , 結果在運行的時候發現單選按鈕沒有被預設選中 由於是複製然後修改個別屬性 ,然後直接使用的 , 所以name值忘記修改了 , 單選框是根據name來判斷選中 . 修改前 類似這樣: 由於是多個地方使用單選按鈕 , 將所有使用了單選按鈕的div ...
  • 對於學習前端的童鞋,css的掌握是必須的。今天就來實現用css畫出一棵聖誕樹。 主要練習的是css裡面border的練習與掌握程度。 在body創建一個主區域<div></div>:我們用border搭建的三角形在主區域內。 改主區域的背景色:可以給設定一個高度 創建第一個三角形: 這裡的每個區域代 ...
  • 前言 本文大概整理下綁定事件的幾種方式,相容IE8- 的方式(如果需要的話),事件委托,阻止傳播,取消預設行為,event對象等。 之前做的多是手機端頁面,監聽事件也一直是 addEventListener ,現代瀏覽器基本都支持addEventListener ,除了萬惡的IE8及更低版本IE。雖 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...