JavaScript——以簡單的方式理解閉包

????? 閉包,在一開始接觸JavaScript的時候就聽說過。首先明確一點,它理解起來確實不復雜,而且它也非常好用。那我們去理解閉包之前,要有什么基礎呢?我個人認為最重要的便是作用域(lexical scope),如果對作用域和作用域鏈不理解的同學最好自己先去學一學,再回過頭來,理解閉包,就更加輕松。

  下面便直接進入主題。

  我們知道一個函數是有作用域的,在函數內部定義的局部變量只有在函數內部才可以訪問的到。一旦函數訪問結束被銷毀,局部變量隨之也會銷毀,無法通過任何方式再次訪問局部變量,除了閉包。也就是說,我們可以通過閉包這一個方法,從函數的外部去訪問到函數內部的變量,即使那個函數已經被銷毀。沒錯,閉包最重要的用法就是,我們只提供某些接口去訪問和修改局部變量,而外部是不能直接訪問到局部變量的。

  說了那么多有關如何使用閉包,我們來看看閉包是長什么樣子的。又到了舉個栗子的環節,依然是最簡單的people和name。

var people = function(){var name = "Yika";var sayName = function(){return name;  //訪問了people函數的局部變量name
        }var setName = function(newName){name = newName;  //訪問了people函數的局部變量name
        }return{sayName: sayName,setName: setName}//返回一個對象
    }var p1 = people();        //函數return的是一個對象,這個對象里有兩個函數sayName和setNameconsole.log(p1.name);     //undefined.   name是people函數里的局部變量,而不是p1對象的屬性,當然為undefinedconsole.log(p1.sayName());//"Yika"p1.setName("Ruyi");       //通過setName函數修改局部變量name的值console.log(p1.sayName());//"Ruyi"

  看完這個例子,想必對閉包多少有個了解啦,除了注釋的內容,下面再做些補充。

  問:為什么局部變量name屬性在people執行完之后,沒有被銷毀呢,反而數值還保存在內存中。

  答: 在例子中,函數注釋那里專門寫了(訪問了people函數的局部變量name)。正是因為people函數里的sayName函數和setName函數訪問了name屬性,并且通過return傳到了p1對象里,成了p1的兩個方法。因為方法一直引用著people函數的局部變量,所以不會被消除,依然會在內存中。這樣便形成了閉包,可以在函數外部訪問到函數內部的局部變量。

  對此,我們可以換個更直觀的寫法。

var people = function(){var name = "Yika";var obj = {sayName: function(){return name;},setName: function(newName){name = newName}};return obj;       //直觀的返回對象
    }
//下面的結果是一樣的。

  當然閉包也不是一直那么好用,特別是在循環里。繼續舉例子

<body><input type="button"/><input type="button"/><input type="button"/><input type="button"/><input type="button"/><input type="button"/><input type="button"/><script type="text/javascript">var oBtn = document.getElementsByTagName('input');for(var i = 0, len = oBtn.length; i < len; i++){oBtn[i].onclick = function(){alert("value = " + i);    //閉包陷阱的發生地!永遠輸出 value = 7
            }}</script>
</body>

  當我們運行上面的代碼的時候,我們是這樣想的,循環一下按鈕,并輸出按鈕所在的序號,但是我們得到的卻永遠是7。其實用我們之前講的閉包會讓變量的值一直保存在內存中的原理想一想,就應該懂了。當我們循環的時候按鈕的點擊事件時,是引用了for循環里的 i 變量。當所有按鈕都綁定了點擊事件后,i 的值也已經變成了7,當然所有的按鈕輸出的都是7啦!怎么解決這個問題也很好辦的,但是我希望留下給大家思考。這里就說一下大致思路吧,我們可以在循環之外創建一個輔助函數,并讓輔助函數return一個綁定當前 i 的函數。

  當然這里我也只是拋磚引玉的介紹了一下閉包,希望可以幫到大家淺顯簡單的了解閉包。

  還是那句話噢,有問題立即指正,我一定會立馬檢查更正,以免誤導了大家!

轉載于:https://www.cnblogs.com/YikaJ/p/4040631.html

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/273524.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/273524.shtml
英文地址,請注明出處:http://en.pswp.cn/news/273524.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

jquery實現二級聯動不與數據庫交互

<select id"pro" name"pro" style"width:90px;"></select> <select id"city" name"city" style"width: 90px"></select> $._cityInfo [{"n":"北京市","c"…

[016]轉--C++拷貝構造函數詳解

一. 什么是拷貝構造函數 首先對于普通類型的對象來說&#xff0c;它們之間的復制是很簡單的&#xff0c;例如&#xff1a; [c-sharp] view plaincopy int a 100; int b a; 而類對象與普通對象不同&#xff0c;類對象內部結構一般較為復雜&#xff0c;存在各種成員變量。下…

js中調用C標簽實現百度地圖

<script type"text/javascript"> //json數組 var jsonArray document.getElementById("restaurant").value; var map new BMap.Map("milkMap"); // 創建地圖實例 <c:forEach items"${restaurantlist}" var"…

jquery較驗組織機構編碼

//*************************組織機構碼較驗************************* function checkOrganizationCode() { var weight [3, 7, 9, 10, 5, 8, 4, 2]; var str 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ; var reg /^([0-9A-Z]){8}-[0-9|X]{1}$/; var organizationcode $("…

自定義GrildView實現單選功能

首先看實現功能截圖&#xff0c;這是一個自定義Dialog,并且里面內容由GrildView 綁定數據源&#xff0c;實現類似單選功能。 首先自定義Dialog&#xff0c;綁定數據源 自定義Dialog彈出框大小方法 最主要實現的就是點擊顏色切換的功能&#xff0c;默認GrildView的每一項都是藍色…

Java數字字符串如何轉化為數字數組

eg&#xff1a; String numberString "0123456789"; 如何轉化為&#xff1a;int[] digitArry new int[]{0,1,2,3,4,5,6,7,8,9}; 解決辦法&#xff1a; char[] digitNumberArray numberString.toCharArray(); int[] digitArry new int[digitString.toCharArray().l…

『重構--改善既有代碼的設計』讀書筆記----序

作為C的程序員&#xff0c;我從大學就開始不間斷的看書&#xff0c;看到如今上班&#xff0c;也始終堅持每天多多少少閱讀技術文章&#xff0c;書看的很多&#xff0c;但很難有一本書&#xff0c;能讓我去反復的翻閱。但唯獨『重構--改善既有代碼的設計』這本書讓我重復看了不下…

微信公共平臺接口開發--Java實現

Java微信實現&#xff0c;采用SpringMVC 架構&#xff0c;采用SAXReader解析XML RequestMapping(value"/extend") public class WeixinController { RequestMapping(value"/weixin") public ModelAndView weixin(HttpServletRequest request,HttpServlet…

最大權閉合圖hdu3996

定義&#xff1a;最大權閉合圖&#xff1a;是有向圖的一個點集&#xff0c;且該點集的所有出邊都指向該集合。即閉合圖內任意點的集合也在改閉合圖內&#xff0c;給每個點分配一個點權值Pu&#xff0c;最大權閉合圖就是使閉合圖的點權之和最大。 最小割建邊方式&#xff1a;源點…

非監督學習的單層網絡分析

這篇博客對應的是Andrew.Ng的那篇文章&#xff1a;An Analysis o f Single-Layer Networks in Unsupervised Feature Learning&#xff0c;文章的主要目的是討論receptive field size&#xff0c;number of hidden nodes&#xff0c; step-stride以及whitening在對卷積網絡模型…

Spring MVC 驗證碼

頁面 <% page language"java" import"java.util.*" pageEncoding"UTF-8"%> <% String path request.getContextPath(); String basePath request.getScheme()"://"request.getServerName()":"request.getServerP…

數據結構實驗之鏈表四:有序鏈表的歸并

數據結構實驗之鏈表四&#xff1a;有序鏈表的歸并 Time Limit: 1000MS Memory limit: 65536K 題目描述 分別輸入兩個有序的整數序列&#xff08;分別包含M和N個數據&#xff09;&#xff0c;建立兩個有序的單鏈表&#xff0c;將這兩個有序單鏈表合并成為一個大的有序單鏈表&…

apk文件編譯到系統文件中的方法(及包含so庫的)

把第三方或自己開發的apk文件編譯到系統文件(system.img)中的方法&#xff1a; 1 (1)源碼編譯后&#xff0c;把apk拷貝到out\target\product\generic\system\app中。 (2) 執行命令make snod , 把添加的spk編到system.img 中 缺點&#xff1a;執行make clean 后&#xff0c;再…

javascript中interval與setTimeOut的區別

setTimeout(code,millisec) //- 在指定時間后執行代碼 code必須&#xff1b; millisec必須&#xff1b; clearTimeout(setTimeoutId) //- 取消 setTimeout() setInterval(code,millisec)&#xff1b;//指定間隔毫秒內循環執行代碼 code必須&#xff1b; millisec必須&a…

java設計模式之單例模式(七種方法)

單例模式&#xff1a;個人認為這個是最簡單的一種設計模式&#xff0c;而且也是在我們開發中最常用的一個設計模式。 單例模式的意思就是只有一個實例。單例模式確保某一個類只有一個實例&#xff0c;而且自行實例化并向整個系統提供這個實例。這個類稱為單例類。我們前面學習的…

java 遍歷map集合

Map<String, String> map new HashMap<String, String>(); map.put("key1", "value1"); map.put("key2", "value2"); map.put("key3", "value3"); //第一種&#xff1a;通過Map.keySet遍…

poj3009 Curling 2.0 深搜

PS&#xff1a;以前看到題目這么長就沒寫下去了。今天做了半天&#xff0c;沒做出來。準備看題解&#xff0c;打開了網站都忍住了&#xff0c;最后還是靠自己做出來的。算是一點進步吧。 分析&#xff1a; 題目的意思沒明白或者理解有偏差都沒辦法做題。看樣例3和樣例4&#xf…

Android監聽事件

ListView事件監聽&#xff1a; setOnItemSelectedListener 鼠標滾動時觸發 setOnItemClickListener 點擊時觸發 EditText事件監聽&#xff1a; setOnKeyListener 獲取焦點時觸發 RadioGroup事件監聽&#xff1a; setOnCheckedChangeListener 點擊時觸發 CheckBox事件監聽&#…

子類能不能繼承父類的構造方法?

class A{ public A(){} // 1:無參數構造方法。 public A(String s){} // 2.}class B extends A{ public B(String s){ super(s); // 3. }}說明&#xff1a;如果沒有1處的無參數構造方法&#xff0c;那么3處一定要主動調用父類帶參數的構造方法。如果有1處的構造方法&#…

基于原生javascript的ajax實現

function getXMLHttpRequest(){if(window.ActiveXObject){//用戶是ie瀏覽器http_requestnew ActiveXObject("Microsoft.XMLHTTP");}else{//其他的瀏覽器http_requestnew XMLHttpRequest();}return http_request;}var httpRequest;function name(){httpRequestgetXMLH…