国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁(yè) > 編程 > JavaScript > 正文

js中的閉包實(shí)例展示

2019-11-19 12:35:50
字體:
供稿:網(wǎng)友

前言

準(zhǔn)確來說,閉包是基于正常的垃圾回收處理機(jī)制下的。也就是說,一般情況一個(gè)函數(shù)(函數(shù)作用域)執(zhí)行完畢,里面聲明的變量會(huì)全部釋放,被垃圾回收器回收。但閉包利用一個(gè)技巧,讓作用域里面的變量,在函數(shù)執(zhí)行完之后依舊保存沒有被垃圾回收處理掉。

閉包

定義

MDN定義

javascriptkit

詞法作用域

閉包的三大特點(diǎn)為:

1、函數(shù)嵌套函數(shù)

2、內(nèi)部函數(shù)可以訪問外部函數(shù)的變量

3、參數(shù)和變量不會(huì)被回收。

作用域鏈
函數(shù)在執(zhí)行的過程中,先從自己內(nèi)部找變量如果找不到,再?gòu)膭?chuàng)建當(dāng)前函數(shù)所在的作用域(詞法作用域)去找, 以 此往上注意找的是變量的當(dāng)前的狀態(tài)

作用域鏈的博客

函數(shù)連同它作用域鏈上的要找的這個(gè)變量,共同構(gòu)成閉包

一般情況下使用閉包主要是為了

  • 封裝數(shù)據(jù)
  • 暫存數(shù)據(jù)

一個(gè)典型的閉包案例

function car(){ var speed = 0 function fn(){ speed++ console.log(speed) } return fn}var speedUp = car()speedUp() //1speedUp() //2

當(dāng)函數(shù)內(nèi)部沒有執(zhí)行以下的代碼時(shí)

function fn(){ speed++ console.log(speed) }return fn

在代碼執(zhí)行完成后,函數(shù)內(nèi)部的局部變量speed就會(huì)被銷毀,由于全局標(biāo)量speedUp一直存在(除非關(guān)閉當(dāng)前頁(yè)面,否則全局變量一直存在),那么函數(shù)內(nèi)部的作用域就沒有辦法被銷毀,里面有東西一直被使用,這點(diǎn)與瀏覽器的垃圾回收機(jī)制相仿,當(dāng)我們執(zhí)行speedUp(),他會(huì)在函數(shù)的詞法作用域下去尋找,函數(shù)里面又返回了一個(gè)fn,因而形成閉包,簡(jiǎn)單的理解為

var speed = 0function fn(){ speed++ console.log(speed)}

這一段代碼形成一個(gè)閉包,如果不return fn,那函數(shù)內(nèi)部的局部變量就會(huì)被銷毀。

我們可以看看上述代碼利用立即執(zhí)行語(yǔ)句和立即執(zhí)行函數(shù)可以怎么演變:

function car(){ var speed = 0 function fn(){ speed++ console.log(speed) } return fn}var speedUp = car()//1function car(){ var speed = 0 return function (){ speed++ console.log(speed) }}var speedUp = car()//2function car(speed){ return function (){ speed++ console.log(speed) }}var speedUp = car(3)//3function car(){ var speed = arguments[0] return function (){ speed++ console.log(speed) }}var speedUp = car()//4function car(){ var speed = 0 return function (){ speed++ console.log(speed) }}//5 car可以不寫,則為匿名函數(shù) var speedUp = (function car(speed){ return function (){ speed++ console.log(speed) }})(3)

閉包的相關(guān)案例

如下代碼輸出多少?如果想輸出3,那如何改造代碼?

var fnArr = [];for (var i = 0; i < 10; i ++) { fnArr[i] = function(){ return i };}console.log( fnArr[3]() ) // 10

同等演變

假設(shè)只有兩層循環(huán):

var fnArr = []for (var i = 0; i < 2; i ++) { fnArr[i] = (function(j){ return function(){ return j }  })(i)}fnArr[3]()//1var fnArr = [] fnArr[0] = (function(j){ return function(){ return j }  })(0)}fnArr[1] = (function(j){ return function(){ return j }  })(1)}fnArr[3]()//2var a = (function(j){ return function(){ return j }  })(0)}var b = (function(j){ return function(){ return j }  })(1)}b()//3var a = (function(j){ return function(){ return j }  })(0)}function fn2(j){ return function(){ return j }}var b = fn2(1)//4var a = (function(j){ return function(){ return j }  })(0)}function fn2(j){ return function(){ return j } return f}var b = fn2(1)//5var 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)

改造后(立即執(zhí)行語(yǔ)句,演變過程)

var fnArr = []for (var i = 0; i < 10; i ++) { fnArr[i] = (function(j){ return function(){ return j }  })(i)}console.log( fnArr[3]() ) // 3var fnArr = []for (var i = 0; i < 10; i ++) { (function(i){ fnArr[i] = function(){ return i }  })(i)}console.log( fnArr[3]() ) // 3var fnArr = []for (let i = 0; i < 10; i ++) { fnArr[i] = function(){ return i } }console.log( fnArr[3]() ) // 3

封裝一個(gè) Car 對(duì)象

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() //30Car.speedUp()Car.get() //31Car.speedDown()Car.get() //3

如下代碼輸出多少?如何連續(xù)輸出 0,1,2,3,4

for(var i=0; i<5; i++){ setTimeout(function(){ console.log('delayer:' + i ) }, 0)}

輸出結(jié)果為:delayer:5(連續(xù)輸出5個(gè)),執(zhí)行setTimeout時(shí),代碼會(huì)掛到任務(wù)隊(duì)列中區(qū),待i遍歷完成之后執(zhí)行,而此時(shí)i = 5,所以輸出delayer:5(連續(xù)輸出5個(gè))

修改后

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() ) // 0console.log( counter() ) // 1console.log( counter2() ) // 0console.log( counter2() ) // 1

補(bǔ)全代碼,實(shí)現(xiàn)數(shù)組按姓名、年紀(jì)、任意字段排序

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'))

寫一個(gè) sum 函數(shù),實(shí)現(xiàn)如下調(diào)用方式

console.log( sum(1)(2) ) // 3console.log( sum(5)(-1) ) // 4

總結(jié)

以上就是這篇文章的全部?jī)?nèi)容了,希望本文的內(nèi)容對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,如果有疑問大家可以留言交流,謝謝大家對(duì)武林網(wǎng)的支持。

發(fā)表評(píng)論 共有條評(píng)論
用戶名: 密碼:
驗(yàn)證碼: 匿名發(fā)表
主站蜘蛛池模板: 崇信县| 海伦市| 凌源市| 合水县| 两当县| 乌兰县| 鹤壁市| 当涂县| 商河县| 正安县| 安徽省| 铜川市| 青龙| 阳城县| 印江| 深水埗区| 来凤县| 东丰县| 临西县| 昌宁县| 寿宁县| 阿克| 禹州市| 伊吾县| 武宁县| 清新县| 台东市| 德格县| 香河县| 光泽县| 山阳县| 富蕴县| 沿河| 宜都市| 年辖:市辖区| 上饶市| 布尔津县| 若尔盖县| 突泉县| 平武县| 左权县|