摘要:在一個閉包環境內修改變量值,不會影響另一個閉包中的變量。直到看到函數閉包閉包這篇文章的代碼一部分,終于明白其中的邏輯了。
閉包
閉包定義:指擁有多個變量和綁定了這些變量的環境的表達式(通常是一個函數),因而這些變量也是該表達式的一部分。
函數內部可以直接讀取全局變量。
函數內部變量無法在函數外部訪問。
函數內部聲明要用var或者let聲明,不然會變成全局變量
鏈式作用域:子對象會一級級向上尋找父對象的變量,父對象的變量子對象都是可見的,反之則不行。
在一個閉包環境內修改變量值,不會影響另一個閉包中的變量。
普通的函數內嵌,內部函數是先執行;而閉包則是:先把內部函數賦給外部函數,然后在執行。
下面這段代碼就是一根典型的閉包
function f1(){ var a = 10; function f2(){ alert(a); } f2(); //① } f1(); //10 ②
f1和f1()的區別不加括號是代碼,加()是執行這段代碼,加return是返回一個值,可以把返回的值賦值給變量,不加return默認返回undefined;
所以①處有三種寫法:
第一種:①處寫f2();,②處調用需要這樣寫f1();。具體執行過程:f1體內調用f2函數,并執行。
第二種:①處寫return f2();,②處調用需這樣寫f1();。具體執行過程:同上;區別是多了個return,因為現在f2函數中沒有返回值,所以f1在調用f2只是執行一下alert(a),f1的返回值是undefined。
第三種:①處寫return f2;,②處調用需這樣寫f1()();。這里返回的是f2函數的代碼,所以在調用f1時要加上2個括號,第一個括號是執行f1函數,第2個括號是執行f2函數,如果①處省略return會報錯。
return和函數調用時是否加括號的意思都明白,但是把它倆結合起來,就搞不清了。
正好今天學閉包時碰上了,順便就把它搞清楚了。
到底什么是閉包對于新人(當然了是說我了),看很多閉包的定義,代碼,還是不知啥是閉包,云里霧里的,這里感謝方方老師的文章JS 中的閉包是什么?,看完后,雖然還是說不出啥是閉包,但現在已經知道啥是閉包了,果然用圖說話最牛逼。(圖在文章中,我就不放出來了)
閉包的應用MDN 上這個例子也寫的很好
調用Counter.value()時,返回的是Counter內部的變量privateCounter;
increment內部沒有返回值,這個方法只是執行了privateCounter + 1操作,沒有返回值;
同理decrement是將privateCounter - 1,也沒有返回值;
所以執行Counter.increment,會返回undefined,但是接著操作Counter.value()時就可以得到1,因為執行上一步Counter.increment時privateCounter被+1了。
今天在下面三段代碼上花費了大量的時間,一直似懂非懂,心里不踏實。
代碼一:
var name = "window"; var obj = { name: "object", getName: function() { return this.name; } }; obj.getName(); //object (obj.getName = obj.getName)(); //window 非嚴格模式下
代碼二:
var name = "window"; var obj = { name: "object", getName: function() { return function(){ return this.name; } } }; obj.getName()(); //window
代碼三:
var name = "window"; var obj = { name : "object", getName : function(){ var that = this; return function(){ return that.name; }; } }; obj.getName()(); //object
今天在看阮一峰的博客學習Javascript閉包(Closure),對代碼二、代碼三部分很是不解,看到一網友搬出犀牛書(還沒看過,我買了紅寶石書才看了一點點)里的話,實在不解什么是作為函數調用,什么是作為方法調用;
《Javascript權威指南》上說:如果嵌套函數作為函數調用,其this值不是全局對象(非嚴格模式下)就是undefined(嚴格模式下); 如果嵌套函數作為方法調用,其this值指向調用它的對象。
又有一位網友說
每個函數在被調用時,其活動對象都會自動取得兩個特殊變量:this和arguments。內部函數在搜索這個變量時,只會搜索到其活動對象為止,因此永遠不可能直接訪問外部函數中的這兩個變量(這一點通過前面的圖可以看得更清楚)。意思就是說找到匿名函數中的this和arguments就不會再往下找了(這里的往下指的是外層的包含函數,和最外層的window全局環境),而匿名函數的this對象通常指向window,所以輸出的是全局的那個字符串。不過,把外部作用域中的this對象保存在一個閉包能夠訪問到的變量里,就可以讓閉包訪問該對象了。
看到這里大概明白匿名函數的作用域是全局,繼續翻看下面評論,大概意思是說“把this保存在obj作用域下的一個變量中,this就在當前函數的作用域下了”。直到看完也是,似懂非懂,反正就是感覺哪里不對勁,但也說不上了。
直到看到【JavaScript】【函數】閉包閉包!這篇文章的代碼一部分,終于明白其中的邏輯了。
下面就來分析其中的邏輯,我分析的方法就是把不懂的地方一個個用console打印出來
代碼二和代碼一的區別是多了一層嵌套函數,this值就不一樣了。
ps:我一開始以為在代碼二中再嵌套一層函數,就會打印出object =_=|||
先來看代碼一,明白之后,另外兩段代碼自然就懂了。
為什么obj.getName()打印出來的是object,因為這時getName方法是在obj的作用域下,所以this指向obj,返回值當然就是object了。
接著看(obj.getName = obj.getName)()刪掉右邊后,打印出的結果變成了object,這就納悶了。
ps:第一眼看上去,這啥玩意,把自己賦值給自己?這不是多此一舉,直接用不就行了!
用console.log打印出obj.getName后,終于撥云見天,obj.getName = obj.getName這句話的意思就是把getName函數賦值給自己,這個時候就不是obj.getName,而是getName匿名函數了,匿名函數通常用的方法是()()立即執行,此時再看匿名函數已經脫離obj了,當然this也就指向了全局,打印出window。
再來看代碼二,用console打印出obj.getName()會發現是一個匿名函數,而匿名函數的this通常會指向全局,所以也就不難理解了
理解上面兩段代碼,代碼三也就很好理解了。
閉包中引用循環變量廖雪峰的閉包在文中就很形象的講解了函數中的引用會變化的變量會有什么后果,我節選了他的結論和代碼。
返回閉包時牢記的一點就是:返回函數不要引用任何循環變量,或者后續會發生變化的變量。
如果一定要引用循環變量怎么辦?方法是再創建一個函數,用該函數的參數綁定循環變量當前的值,無論該循環變量后續如何更改,已綁定到函數參數的值不變:
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
這里的核心就是立即執行,如果不是立即執行的話,變量i就是for循環結束后的值了。
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://m.specialneedsforspecialkids.com/yun/95041.html
摘要:本筆記共四篇源碼閱讀筆記源碼閱讀筆記源碼閱讀筆記服務器啟動與請求處理源碼閱讀筆記對象起因前兩天終于把自己一直想讀的源代碼讀了一遍。首先放上關鍵的源代碼在上一篇源碼閱讀筆記服務器啟動與請求處理中,我們已經分析了的作用。 本筆記共四篇Koa源碼閱讀筆記(1) -- coKoa源碼閱讀筆記(2) -- composeKoa源碼閱讀筆記(3) -- 服務器の啟動與請求處理Koa源碼閱讀筆記(4...
摘要:從最開始的到封裝后的都在試圖解決異步編程過程中的問題。為了讓編程更美好,我們就需要引入來降低異步編程的復雜性。異步編程入門的全稱是前端經典面試題從輸入到頁面加載發生了什么這是一篇開發的科普類文章,涉及到優化等多個方面。 TypeScript 入門教程 從 JavaScript 程序員的角度總結思考,循序漸進的理解 TypeScript。 網絡基礎知識之 HTTP 協議 詳細介紹 HTT...
摘要:原文地址一個非常適合入門學習的博客項目前端掘金一個非常適合入門學習的項目,代碼清晰結構合理新聞前端掘金介紹一個由編寫的新聞。深入淺出讀書筆記知乎專欄前端專欄前端掘金去年的一篇老文章,恰好今天專欄開通,遷移過來。 破解前端面試(80% 應聘者不及格系列):從閉包說起 - 掘金修訂說明:發布《80% 應聘者都不及格的 JS 面試題》之后,全網閱讀量超過 6W,在知乎、掘金、cnodejs ...
摘要:原文地址一個非常適合入門學習的博客項目前端掘金一個非常適合入門學習的項目,代碼清晰結構合理新聞前端掘金介紹一個由編寫的新聞。深入淺出讀書筆記知乎專欄前端專欄前端掘金去年的一篇老文章,恰好今天專欄開通,遷移過來。 破解前端面試(80% 應聘者不及格系列):從閉包說起 - 掘金修訂說明:發布《80% 應聘者都不及格的 JS 面試題》之后,全網閱讀量超過 6W,在知乎、掘金、cnodejs ...
閱讀 1213·2021-09-03 10:44
閱讀 613·2019-08-30 13:13
閱讀 2804·2019-08-30 13:11
閱讀 1973·2019-08-30 12:59
閱讀 1040·2019-08-29 15:32
閱讀 1603·2019-08-29 15:25
閱讀 998·2019-08-29 12:24
閱讀 1288·2019-08-27 10:58