您好,登錄后才能下訂單哦!
這篇文章主要介紹了js閉包的示例分析,具有一定借鑒價值,感興趣的朋友可以參考下,希望大家閱讀完這篇文章之后大有收獲,下面讓小編帶著大家一起了解一下。
準確來說,閉包是基于正常的垃圾回收處理機制下的。也就是說,一般情況一個函數(函數作用域)執行完畢,里面聲明的變量會全部釋放,被垃圾回收器回收。但閉包利用一個技巧,讓作用域里面的變量,在函數執行完之后依舊保存沒有被垃圾回收處理掉。
閉包
定義
MDN定義
javascriptkit
詞法作用域
作用域鏈
函數在執行的過程中,先從自己內部找變量如果找不到,再從創建當前函數所在的作用域(詞法作用域)去找, 以 此往上注意找的是變量的當前的狀態
作用域鏈的博客
函數連同它作用域鏈上的要找的這個變量,共同構成閉包
一般情況下使用閉包主要是為了
封裝數據
暫存數據
一個典型的閉包案例
function car(){ var speed = 0 function fn(){ speed++ console.log(speed) } return fn } var speedUp = car() speedUp() //1 speedUp() //2
當函數內部沒有執行以下的代碼時
function fn(){ speed++ console.log(speed) } return fn
在代碼執行完成后,函數內部的局部變量speed就會被銷毀,由于全局標量speedUp一直存在(除非關閉當前頁面,否則全局變量一直存在),那么函數內部的作用域就沒有辦法被銷毀,里面有東西一直被使用,這點與瀏覽器的垃圾回收機制相仿,當我們執行speedUp(),他會在函數的詞法作用域下去尋找,函數里面又返回了一個fn,因而形成閉包,簡單的理解為
var speed = 0 function fn(){ speed++ console.log(speed) }
這一段代碼形成一個閉包,如果不return fn,那函數內部的局部變量就會被銷毀。
我們可以看看上述代碼利用立即執行語句和立即執行函數可以怎么演變:
function car(){ var speed = 0 function fn(){ speed++ console.log(speed) } return fn } var speedUp = car() //1 function car(){ var speed = 0 return function (){ speed++ console.log(speed) } } var speedUp = car() //2 function car(speed){ return function (){ speed++ console.log(speed) } } var speedUp = car(3) //3 function car(){ var speed = arguments[0] return function (){ speed++ console.log(speed) } } var speedUp = car() //4 function car(){ var speed = 0 return function (){ speed++ console.log(speed) } } //5 car可以不寫,則為匿名函數 var speedUp = (function car(speed){ return function (){ speed++ console.log(speed) } } )(3)
閉包的相關案例
如下代碼輸出多少?如果想輸出3,那如何改造代碼?
var fnArr = []; for (var i = 0; i < 10; i ++) { fnArr[i] = function(){ return i }; } console.log( fnArr[3]() ) // 10
同等演變
假設只有兩層循環:
var fnArr = [] for (var i = 0; i < 2; i ++) { fnArr[i] = (function(j){ return function(){ return j } })(i) } fnArr[3]() //1 var fnArr = [] fnArr[0] = (function(j){ return function(){ return j } })(0) } fnArr[1] = (function(j){ return function(){ return j } })(1) } fnArr[3]() //2 var a = (function(j){ return function(){ return j } })(0) } var b = (function(j){ return function(){ return j } })(1) } b() //3 var a = (function(j){ return function(){ return j } })(0) } function fn2(j){ return function(){ return j } } var b = fn2(1) //4 var a = (function(j){ return function(){ return j } })(0) } function fn2(j){ return function(){ return j } return f } var b = fn2(1) //5 var a = (function(j){ return function(){ return j } })(0) } function fn2(j){ var j = arguments[0] function f(){ return j } return f } var b = fn2(1)
改造后(立即執行語句,演變過程)
var fnArr = [] for (var i = 0; i < 10; i ++) { fnArr[i] = (function(j){ return function(){ return j } })(i) } console.log( fnArr[3]() ) // 3 var fnArr = [] for (var i = 0; i < 10; i ++) { (function(i){ fnArr[i] = function(){ return i } })(i) } console.log( fnArr[3]() ) // 3 var fnArr = [] for (let i = 0; i < 10; i ++) { fnArr[i] = function(){ return i } } console.log( fnArr[3]() ) // 3
封裝一個 Car 對象
var Car = (function(){ var speed = 0; function set(s){ speed = s } function get(){ return speed } function speedUp(){ speed++ } function speedDown(){ speed-- } return { setSpeed: setSpeed, get: get, speedUp: speedUp, speedDown: speedDown } })() Car.set(30) Car.get() //30 Car.speedUp() Car.get() //31 Car.speedDown() Car.get() //3
如下代碼輸出多少?如何連續輸出 0,1,2,3,4
for(var i=0; i<5; i++){ setTimeout(function(){ console.log('delayer:' + i ) }, 0) }
輸出結果為:delayer:5(連續輸出5個),執行setTimeout時,代碼會掛到任務隊列中區,待i遍歷完成之后執行,而此時i = 5,所以輸出delayer:5(連續輸出5個)
修改后
for(var i=0; i<5; i++){ (function(j){ setTimeout(function(){ console.log('delayer:' + j ) }, 0)//1000-1000*j })(i) }
或者
for(var i=0; i<5; i++){ setTimeout((function(j){ return function(){ console.log('delayer:' + j ) } }(i)), 0) }
如下代碼輸出多少?
function makeCounter() { var count = 0 return function() { return count++ }; } var counter = makeCounter() var counter2 = makeCounter(); console.log( counter() ) // 0 console.log( counter() ) // 1 console.log( counter2() ) // 0 console.log( counter2() ) // 1
補全代碼,實現數組按姓名、年紀、任意字段排序
var users = [ { name: "John", age: 20, company: "Baidu" }, { name: "Pete", age: 18, company: "Alibaba" }, { name: "Ann", age: 19, company: "Tecent" } ] users.sort(byName) users.sort(byAge) users.sort(byField('company'))
解答
function byName(user1, user2){ return user1.name > user2.name } function byAge (user1, user2){ return user1.age > user2.age } function byFeild(field){ return function(user1, user2){ return user1[field] > user2[field] } } users.sort(byField('company'))
寫一個 sum 函數,實現如下調用方式
console.log( sum(1)(2) ) // 3 console.log( sum(5)(-1) ) // 4
感謝你能夠認真閱讀完這篇文章,希望小編分享的“js閉包的示例分析”這篇文章對大家有幫助,同時也希望大家多多支持億速云,關注億速云行業資訊頻道,更多相關知識等著你來學習!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。