日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 前端技术 > javascript >内容正文

javascript

JavaScript 闭包详解

發布時間:2025/3/19 javascript 24 豆豆
生活随笔 收集整理的這篇文章主要介紹了 JavaScript 闭包详解 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

2019獨角獸企業重金招聘Python工程師標準>>>

閉包是什么?

閉包(英語:Closure),又稱詞法閉包(Lexical Closure)或函數閉包(Function Closures),是引用了自由變量的函數。這個被引用的自由變量將和這個函數一同存在,即使已經離開了創造它的環境也不例外。所以,有另一種說法認為閉包是函數和聲明該函數的詞法環境的組合。你也可以理解為閉包就是一個帶狀態(狀態即引用的自由變量)的函數。

?

1、函數作為返回值

在高階函數中函數不僅可以作為參數進行傳遞,還可以作為返回值返回。

?我們先來實現一個兩個數字相加的例子

function add(x, y) {return x + y; } add(1, 2) // 3

但是如果我們不想立馬計算,在后面根據需求在進行計算應該怎么辦?答案是返回求和的方法,而不是返回求和的結果。

function lazy_add(x, y) {var add = function(x, y) {return x + y;}return add; }

當我們調用lazy_add()?時返回的并不是求和的結果,而是返回的求和函數

var fun = lazy_add(1, 2) // function add(){}

當真正需要進行計算的時候我們可以調用fun()

var sum = fun(); //3

那么我們調用的是fun方法,也并沒有將他怎么就知道是1和2相加了呢?原因就是fun方法是通過lazy_add方法傳遞兩個參數1和2生成的,lazy_add方法在返回add方法的同時將變量x和y也一并保存返回了。這就形成了自由變量x,y和函數add組成的閉包。

需要注意的是,當我們調用lazy_add()時,每次調用都會返回一個新的函數,即使傳入相同的參數:

var f1 = lazy_add(1, 2); var f2 = lazy_sum(1, 2); f1 === f2; // false

?

2、循環中的閉包

?我們再看一個例子

function count() {var arr = [];for (var i=1; i<=3; i++) {arr.push(function () {return i * i;});}return arr; }var results = count(); var f1 = results[0]; var f2 = results[1]; var f3 = results[2];

在上面的代碼中在每次循環中生成了一個函數放到了數組中。你可能認為調用f1()f2()f3()結果應該是149,但實際結果是:三個都是 16

為什么會這樣呢?原因就在于返回的函數引用了變量i,但它并非立刻執行。等到3個函數都返回時,它們所引用的變量i已經變成了4,因此最終結果為16

所以返回閉包時牢記的一點就是:返回函數不要引用任何循環變量,或者后續會發生變化的變量

如果非要引用循環變量應該怎么辦?那就是在循環變量的外層包一層立即執行函數,將循環變量綁定到立即執行函數的入參,如下:

function count() {var arr = [];for (var i=1; i<=3; i++) {arr.push((function (n) {return function () {return n * n;}})(i));}return arr; }var results = count(); var f1 = results[0]; var f2 = results[1]; var f3 = results[2];f1(); // 1 f2(); // 4 f3(); // 9

另外可以通過ES6中的語法更輕松地解決這個問題,那就是通過let聲明循環變量,該方法可以避免使用過多的閉包(過多的閉包影響性能)代碼如下:

function count() {var arr = [];for (let i=1; i<=3; i++) {arr.push(function () {return i * i;});}return arr; }var results = count(); var f1 = results[0]; var f2 = results[1]; var f3 = results[2];

這個例子使用let而不是var,因此每個閉包都綁定了塊作用域的變量,這意味著不再需要額外的閉包。

說了這么多,難道閉包就是為了返回一個函數然后延遲執行嗎?當然不是!讓我們接著往下看。

?

3、函數柯里化(curry)

柯里化(Currying)是把接受多個參數的函數變換成接受一個單一參數(最初函數的第一個參數)的函數,并且返回接受余下的參數且返回結果的新函數的技術。讀起來可能優點繞,看了下面的例子你就會明白。

想必大家應該都用過 Math.pow(x, y)方法,是的這個就是計算x的y次方的方法,但是由于我們通常都是計算2次方和3次方,所以我們要通過閉包基數對該方法進行柯里化。

function make_pow(n) {return function (x) {return Math.pow(x, n);} }//創建兩個新的方法 var pow2 = make_pow(2); var pow3 = make_pow(3);pow2(5); // 25 pow3(5); // 125

?

4、對象封裝

在面向對象的程序設計語言里,比如Java和C++,要在對象內部封裝一個私有變量,可以用private修飾一個成員變量。

在沒有class機制,只有函數的語言里,借助閉包,同樣可以封裝一個私有變量。下面我們就用javascript創建一個包含私有變量的計數器。

function create_counter(initial) {var x = initial || 0;return {inc: function () {x += 1;return x;}} }var c1 = create_counter(1); c1.inc(); // 2 c1.inc(); // 3 c1.inc(); // 4

在返回的對象中,實現了一個閉包,該閉包攜帶了局部變量x,并且,從外部代碼根本無法訪問到變量x?

?

5、閉包性能考量

如果不是某些特定任務需要使用閉包,在其它函數中創建函數是不明智的,因為閉包在處理速度和內存消耗方面對腳本性能具有負面影響。

例如,在創建新的對象或者類時,方法通常應該關聯于對象的原型,而不是定義到對象的構造器中。原因是這將導致每次構造器被調用時,方法都會被重新賦值一次(也就是,每個對象的創建)。

function MyObject(name, message) {this.name = name.toString();this.message = message.toString(); } MyObject.prototype.getName = function() {return this.name; }; MyObject.prototype.getMessage = function() {return this.message; };var obj1 = new MyObject('name1', 'message1'); var obj2 = new MyObject('name2', 'message2'); obj1.getName == obj2.getName; // true

上面的代碼中構造的每個實例中的方法都指向同一個

但是如果是用閉包封裝的對象會怎么樣,接著用之前的計數器例子做一下測試

var count1 = create_counter(1); var count2 = create_counter(2);count1.inc == count2.int; //false

從測試結果可以看出每個對象中的方法都是獨立的方法,這樣違背了對象方法公用原則

萬物皆有利弊,所以具體要怎么使用還是要仔細考量。

轉載于:https://my.oschina.net/kimyeongnam/blog/733809

總結

以上是生活随笔為你收集整理的JavaScript 闭包详解的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。

主站蜘蛛池模板: 成人小视频在线播放 | 欧美日韩视频无码一区二区三 | 网站黄在线观看 | 中国女人一级片 | 波多野结衣人妻 | 日日插日日操 | av一区不卡 | 精品视频久久久久久 | 国产日韩片| 欧美激情三级 | 毛茸茸毛片 | 欧美h视频在线观看 | 性盈盈影院中文字幕 | 污视频大全 | 男人日女人在线观看 | 外国电影免费观看高清完整版 | 国产一卡二卡在线播放 | 超碰天堂 | 888奇米影视 | 老司机深夜福利视频 | 日本免费网站在线观看 | 91看片在线看 | 日本一区二区三区免费电影 | 日韩视频一区二区三区在线播放免费观看 | 中文字幕在线观看欧美 | 午夜视频大全 | 日韩在线视频观看 | 98视频在线 | 国产免费a | 视频毛片| 无码人妻一区二区三区在线 | 免费a在线观看 | 色射综合 | 亚洲精品一区中文字幕乱码 | 毛片无遮挡高清免费观看 | 337p色噜噜 | 曰批又黄又爽免费视频 | 韩国短剧在线观看 | 成人国产av一区二区三区 | 午夜免费片 | 国产又黄又粗又硬 | 狂野欧美性猛交xxxx | 永久精品网站 | 99er在线| 成人毛片大全 | 懂色av粉嫩av蜜乳av | 国产精品无码一区二区无人区多人 | 日韩欧美一区二区三区在线 | 午夜性色福利视频 | 高清国产一区二区三区四区五区 | 国产精品12页 | 精品人妻一区二区三区蜜桃视频 | 在线观看第一页 | 二区在线播放 | 国产成人一区二区三区影院在线 | 欧美日韩亚洲成人 | 奇米影视中文字幕 | 久久久久草| 欧美日韩a√ | 国产精品久久久久高潮 | 综合伊人av | 性生交大片免费看3p | 中文字幕av在线免费 | 成人av网站在线 | 久草剧场| 19禁大尺度做爰无遮挡电影 | 精品一区二区三区在线播放 | 国产欧美久久一区二区三区 | 久久久久久久久久久久 | 性欧美熟妇videofreesex | 免费av电影网址 | 少妇自拍视频 | 国产毛片在线视频 | av片观看| 在线一区视频 | www.夜夜夜 | 日日干日日 | 午夜视频免费在线 | 中文字幕理伦片免费看 | 免费视频一区二区 | 成年女人免费视频 | 激情欧美一区二区 | 日韩插插 | 日韩精品亚洲精品 | 久久久免费精品视频 | av一级二级 | 91亚洲网站| 99久久影视 | 日韩制服在线 | 亚洲av无码一区二区二三区 | 国产黄网在线观看 | 欧美日韩国产精品成人 | av成人在线播放 | 国产1区在线观看 | 亚洲av综合色区 | 福利免费在线观看 | 99国产精品免费视频 | 国产日韩一区二区在线观看 | 色偷偷网站 |