摘要:理解了這句話,我們就可以來看閉包了閉包前面說過,函數可以訪問函數作用域鏈中的變量,但如果我們想在函數外訪問函數內卻不行了。
不管是閉包還是this關鍵字,都是困擾JS初學者的比較難懂的東西,如果你對它們的認識還不足夠清晰,那么現在就一起把它們掌握掉。還是那句話,我們從最基本的開始,建立起一個非常清晰的知識結構,好了,開始吧 ?
閉包當然我們今天說的是javascript里的閉包。要學習閉包,首先需要明白函數和變量,其次要知道變量和函數的一些特性。來復習一下:
變量變量是那些會變化的東西(就這么簡單),變量有一個值,我們能改變這個值。我們先聲明一個變量名,然后對這個變量賦值,就創建了一個變量。變量分按作用域(這個很重要后面會講到)為全局變量和局部變量。
函數我們最初學習的是通過函數聲明來創建一個函數,即首先是 function 關鍵字,然后是函數的名字,這就是指定函數名的方式。另一個方式叫做函數表達式,最常見的形式是這樣的:
var functionName = function(arg0, arg1, arg2){ //函數體 };
我們創建的這個函數叫做匿名函數,因為 function 關鍵字后面沒有標識符,沒有名字嘛。
結合函數和作用域,我們來小小地總結一下:函數內可以讀取函數外的變量,而函數外卻讀取不了函數內部的變量(局部變量)。理解了這句話,我們就可以來看閉包了:
前面說過,函數可以訪問函數作用域鏈中的變量,但如果我們想在函數外訪問函數內卻不行了。比如這個例子:
function myfunction(){ var num=21; } alert(num); // error
眼前就有一個變量,尷尬的是我們調用不了。
想想辦法:根據函數可以訪問函數作用域鏈中的變量這句話,如果我們在函數內再定義一個函數,讓這個新函數訪問舊函數里的變量,然后返回這個函數,然后直接運行那個舊函數不就可以了嗎!
function myfunction(){ var num=21; function newfunction(){ alert(num); } return newfunction; } var result=myfunction(); result(); // 21
沒有任何問題,在函數外面成功訪問到了num變量。
恭喜你,你剛剛創建了一個閉包。。。是的,這個就是閉包。閉包就是指有權訪問另一個函數作用域中的變量的函數。創建閉包的常見方式,就是在一個函數內部創建另一個函數。
明白了閉包,再來看為什么可以把閉包和this放一起理解:
this關鍵字首先你需要記住的是:this的對象是運行時基于函數的執行環境綁定的,它的指向完全取決于函數的調用方式
不多說來看兩個經典例子:
第1個例子
var name = "The Window"; var object = { name : "My Object", getNameFunc : function(){ return function(){ return this.name; }; } }; alert(object.getNameFunc()()); //"The Window"(在非嚴格模式下)
第2個例子
var name = "The Window"; var object = { name : "My Object", getNameFunc : function(){ var that = this; return function(){ return that.name; }; } }; alert(object.getNameFunc()()); //"My Object"
關于這兩個例子,我個人感覺《Javascript高級程序設計》這本書里講得不夠明確。我的理解是第1個例子里是在全局環境中調用了這個函數,所以this關鍵字最終指向了全局對象The Window,從而利用閉包在全局環境中調用了The Window;第2個例子不同,它返回的是that的name,而this對象被賦值給了that變量,就是說this對象和that捆綁在了一起,那么在調用這個方法時相當于在object里利用閉包去尋找最終變量(that是引用著object的),所以只能找到My Object變量。
這兩個例子非常好,怎么個好法呢。它們完整解釋(展現)了閉包的作用機理或者說過程,同時又證明了this關鍵字在函數被不同的環境調用時的指向是不一樣的。
怎么樣,看到這里是不是徹底明白了閉包和this關鍵字呢。
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/88488.html
摘要:是完全的面向對象語言,它們通過類的形式組織函數和變量,使之不能脫離對象存在。而在基于原型的面向對象方式中,對象則是依靠構造器利用原型構造出來的。 JavaScript 函數式腳本語言特性以及其看似隨意的編寫風格,導致長期以來人們對這一門語言的誤解,即認為 JavaScript 不是一門面向對象的語言,或者只是部分具備一些面向對象的特征。本文將回歸面向對象本意,從對語言感悟的角度闡述為什...
摘要:忍者級別的函數操作對于什么是匿名函數,這里就不做過多介紹了。我們需要知道的是,對于而言,匿名函數是一個很重要且具有邏輯性的特性。通常,匿名函數的使用情況是創建一個供以后使用的函數。 JS 中的遞歸 遞歸, 遞歸基礎, 斐波那契數列, 使用遞歸方式深拷貝, 自定義事件添加 這一次,徹底弄懂 JavaScript 執行機制 本文的目的就是要保證你徹底弄懂javascript的執行機制,如果...
摘要:函數式編程前端掘金引言面向對象編程一直以來都是中的主導范式。函數式編程是一種強調減少對程序外部狀態產生改變的方式。 JavaScript 函數式編程 - 前端 - 掘金引言 面向對象編程一直以來都是JavaScript中的主導范式。JavaScript作為一門多范式編程語言,然而,近幾年,函數式編程越來越多得受到開發者的青睞。函數式編程是一種強調減少對程序外部狀態產生改變的方式。因此,...
摘要:之前一篇文章我們詳細說明了變量對象,而這里,我們將詳細說明作用域鏈。而的作用域鏈,則同時包含了這三個變量對象,所以的執行上下文可如下表示。下圖展示了閉包的作用域鏈。其中為當前的函數調用棧,為當前正在被執行的函數的作用域鏈,為當前的局部變量。 showImg(https://segmentfault.com/img/remote/1460000008329355);初學JavaScrip...
摘要:設計模式是以面向對象編程為基礎的,的面向對象編程和傳統的的面向對象編程有些差別,這讓我一開始接觸的時候感到十分痛苦,但是這只能靠自己慢慢積累慢慢思考。想繼續了解設計模式必須要先搞懂面向對象編程,否則只會讓你自己更痛苦。 JavaScript 中的構造函數 學習總結。知識只有分享才有存在的意義。 是時候替換你的 for 循環大法了~ 《小分享》JavaScript中數組的那些迭代方法~ ...
閱讀 2106·2021-11-24 09:39
閱讀 1495·2019-08-30 15:44
閱讀 1946·2019-08-29 17:06
閱讀 3393·2019-08-29 16:32
閱讀 3543·2019-08-29 16:26
閱讀 2654·2019-08-29 15:35
閱讀 3026·2019-08-29 12:50
閱讀 1636·2019-08-29 11:15