您好,登錄后才能下訂單哦!
這期內容當中小編將會給大家帶來有關閉包怎么在javascript中使用,文章內容豐富且以專業的角度為大家分析和敘述,閱讀完這篇文章希望大家可以有所收獲。
閉包的概念:閉包是指有權訪問另一個函數作用域中的變量的函數 (引自《javascript高級程序設計第三版》178頁)。閉包的優點是不會產生全局變量,避免變量污染問題,但是閉包也有一個缺點就是閉包攜帶包含它的函數作用域會比其它函數占用更多的內存,過度使用會導致內存占用過多。
wiki上關于閉包的概念:
In programming languages, closures (also lexical closures or function closures) are techniques for implementing lexically scoped name binding in languages with first-class functions. Operationally, a closure is a record storing a function[a] together with an environment:[1] a mapping associating each free variable of the function (variables that are used locally, but defined in an enclosing scope) with the value or reference to which the name was bound when the closure was created.[b] A closure—unlike a plain function—allows the function to access those captured variables through the closure's copies of their values or references, even when the function is invoked outside their scope.
簡單來說:閉包是一個存儲了函數以及與這個函數相關的環境信息的記錄。
閉包實踐一:初次體驗閉包
function a() { var temp = 100; function b() { console.log(++temp); } return b; } var fn = a(); // 此時fn屬于全局的函數。 fn();// 101 fn();// 102
在函數a的內部return出了一個局部函數b。讓函數fn接收函數a的返回值,也就是函數b。連續執行了兩次fn,輸出結果101,,102表示,函數fn一直引用著函數a中的局部變量temp。每次調用fn,temp都會被自增1。從此處說明了函數a一直沒有被垃圾回收機制(GC)回收。以上代碼還可以這樣優化:
function a() { var temp = 100; return function() { console.log(++temp); } } var fn = a(); a = null; fn();// 101 fn();// 102 fn = null; // 調用完畢后要,要解除對內部匿名函數的引用,以便釋放內存
閉包實踐二:閉包與變量
分析下面的代碼
html結構:
<ul> <li>0</li> <li>1</li> <li>2</li> </ul>
javascript結構:
var ul = document.querySelector('ul');// 為了演示方便,直接用html5的api var lis = ul.children; for(var i=0; i< lis.length; i++) { lis[i].οnclick=function(){ console.log(i); } }
當點擊每個li時,輸出的全都是3,在點擊事件之前,for循環早已經執行完了,i的值為3。為了防止這種情況發生,for循環還可以修改成這樣:
for(var i=0; i< lis.length; i++) { lis[i].οnclick=function(num){ return function(){ console.log(num); } }(i) }
由于函數是按值傳遞的,所以就會將變量i的當前值賦給num,而在函數內部又返回了一個訪問num的閉包。這樣每次i的值就保存下來了。值得一提的是在ECMAScript6中可以用嚴格模式下用let 來聲明i。這樣可以直接保存i,有關es6,以后再深入學習,示例代碼如下:
javascript結構:
'use strict' let ul = document.querySelector('ul'); let lis = ul.children; for(let i=0; i< lis.length; i++) { lis[i].οnclick=function(){ console.log(i); } }
閉包實踐三:對實踐二的深層剖析,閉包保存的是整個變量對象,而不是某個特殊的變量。(出自 《javascript高級程序設計第三版》 181頁)
/* createFunctions方法返回一個函數數組 result */ function createFunctions() { var result = new Array(); for(var i=0; i<10;i++) { result[i] = function() { return i; } } return result; } var arr = createFunctions(); // 我們拿到并輸出第一個數組元素函數的返回值 var fn0 = arr[0]; var varible0 = fn0(); console.log(varible0); // 返回的是 10 // 我們拿到并輸出第二個數組元素函數的返回值 var fn1 = arr[1]; var varible1 = fn1(); console.log(varible1); // 返回的是 10 // 可見閉包保存的是這個變量i對象,i的最終結果是10
我們只要對代碼稍稍優化,用自執行函數來處理,就可以達到我們的預期了,如下:
function createFunctions() { var result = new Array(); for(var i=0; i<10;i++) { result[i] = (function(num) { return function(){ return num; } })(i) } return result; } var arr = createFunctions(); // 我們拿到并輸出第一個數組元素函數的返回值 var fn0 = arr[0]; var varible0 = fn0(); console.log(varible0); // 返回的是 0 // 我們拿到并輸出最后一個數組元素函數的返回值 var fn9 = arr[9]; var varible9 = fn9(); console.log(varible9); // 返回的是 9
閉包實踐四:閉包與this 使用不同的編程方式使用閉包,this指向不同的對象
var color = 'black'; var person = { color:"yellow", getColorFun1:function(){ return function(){ return this.color; } }, getColorFun2:function(){ var that = this; return that.color; } } console.log(person.getColorFun1()()); // 指向了 black (備注:fn()()這種寫法只限于非嚴格模式下) console.log(person.getColorFun2()); // 指向了yellow
說明:當調用到person.getColorFun1()
的時候,在全局變量中生成一個函數function(){return this.color}
,此時的this指向是window,所以執行到person.getColorFun1()()
的時候,color為window對象下的變量color為black
而在person.getColorFun2
函數中用that保存了當前對象person,而在閉包函數里面return出去的color是person的color,所以執行完person.getColorFun2()()
的時,color是yellow。
實踐四:閉包的高級應用
示例1:實現函數節流
window.onresize = throttle(function(){ var width = window.innerWidth || document.documentElement.clientWidth; console.log(width); },300); // 調節瀏覽器窗口,在松手后的0.3s后執行 function throttle(fn,delay) { var timer = null; return function() { clearTimeout(timer); timer = setTimeout(fn,delay); } }
示例2:實現封裝對象
var Person = (function(){ var haha = 0; // 這里表示可以定義一能夠使用到的參數 return function(name, age){ ++ haha; // 這里表示去使用定義到的參數,雖然在此處并沒有實際意義。 this.name = name; this.age = age; }; })(); Person.prototype = { say : function(){ console.log(this.name + ' say hi'); } } var p1 = new Person('zhang san', 10); var p2 = new Person('li si', 20); console.log(p1.name); // zhang san p1.say(); // zhang san say hi p2.say(); // li si say hi
javascript是一種動態類型、弱類型的語言,基于對象和事件驅動并具有相對安全性并廣泛用于客戶端網頁開發的腳本語言,同時也是一種廣泛用于客戶端Web開發的腳本語言。它主要用來給HTML網頁添加動態功能,現在JavaScript也可被用于網絡服務器,如Node.js。
上述就是小編為大家分享的閉包怎么在javascript中使用了,如果剛好有類似的疑惑,不妨參照上述分析進行理解。如果想知道更多相關知識,歡迎關注億速云行業資訊頻道。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。