摘要:理解二包含被引用變量函數的對象極少數人。在函數外部能直接訪問函數內部的局部變量嗎不能但我們可以通過閉包讓外部操作它。死亡在嵌套的內部函數成為垃圾對象時。
JavaScript函數高級——閉包 一、引子實例
二、理解閉包00_引入
(1)如何產生閉包?
當一個嵌套的內部(子)函數引用了嵌套的外部(父)函數的變量(函數)時, 就產生了閉包。
(2)閉包到底是什么?
使用chrome調試查看。
理解一: 閉包是嵌套的內部函數(絕大部分人)。
理解二: 包含被引用變量(函數)的對象(極少數人)。
注意: 閉包存在于嵌套的內部函數中。
(3)產生閉包的條件?
函數嵌套
內部函數引用了外部函數的數據(變量/函數)
三、常見的閉包(1)將函數作為另一個函數的返回值
// 1. 將函數作為另一個函數的返回值 function fn1() { var a = 2 function fn2() { a++ console.log(a) } return fn2 } var f = fn1() f() // 3 f() // 4
(2)將函數作為實參傳遞給另一個函數調用
// 2. 將函數作為實參傳遞給另一個函數調用 function showDelay(msg, time) { setTimeout(function () { alert(msg) }, time) } showDelay("atguigu", 2000)四、閉包的作用
(1)使用函數內部的變量在函數執行完后, 仍然存活在內存中(延長了局部變量的生命周期)
(2)讓函數外部可以操作(讀寫)到函數內部的數據(變量/函數)
function fn1() { var a = 2 function fn2() { a++ console.log(a) // return a } function fn3() { a-- console.log(a) }- return fn3 } var f = fn1() f() // 1 f() // 0
問題:
函數執行完后, 函數內部聲明的局部變量是否還存在?
一般是不存在, 存在于閉包中的變量才可能存在。
在函數外部能直接訪問函數內部的局部變量嗎?
不能, 但我們可以通過閉包讓外部操作它。
五、閉包的生命周期(1)產生: 在嵌套內部函數定義執行完時就產生了(不是在調用時)。
(2)死亡: 在嵌套的內部函數成為垃圾對象時。
function fn1() { //此時閉包就已經產生了(函數提升, 內部函數對象已經創建了) var a = 2 function fn2 () { a++ console.log(a) } return fn2 } var f = fn1() f() // 3 f() // 4 f = null //閉包死亡(包含閉包的函數對象成為垃圾對象)六、閉包的應用:自定義JS模塊
閉包的應用 : 定義JS模塊
具有特定功能的js文件。
將所有的數據和功能都封裝在一個函數內部(私有的)。
只向外暴露一個包含n個方法的對象或函數。
模塊的使用者, 只需要通過模塊暴露的對象調用方法來實現對應的功能。
第一種方式:
// myModule.js function myModule() { //私有數據 var msg = "My data" //操作數據的函數 function doSomething() { console.log("doSomething() "+msg.toUpperCase()) } function doOtherthing () { console.log("doOtherthing() "+msg.toLowerCase()) } //向外暴露對象(給外部使用的方法) return { doSomething: doSomething, doOtherthing: doOtherthing } }
// 使用模塊:
第二種方式:
// myModule2.js (function () { //私有數據 var msg = "My atguigu" //操作數據的函數 function doSomething() { console.log("doSomething() "+msg.toUpperCase()) } function doOtherthing () { console.log("doOtherthing() "+msg.toLowerCase()) } //向外暴露對象(給外部使用的方法) window.myModule2 = { doSomething: doSomething, doOtherthing: doOtherthing } })()
// 使用模塊七、閉包的缺點及解決
(1)缺點
函數執行完后, 函數內的局部變量沒有釋放, 占用內存時間會變長。
容易造成內存泄露。
(2)解決
能不用閉包就不用。
及時釋放。
function fn1() { var arr = new Array(10000000) function fn2() { console.log(arr.length) } return fn2 } var f = fn1() f() f = null //讓內部函數成為垃圾對象-->回收閉包八、閉包_面試題
面試題1:
//代碼片段一 var name = "The Window"; var object = { name : "My Object", getNameFunc : function(){ return function(){ return this.name; }; } }; alert(object.getNameFunc()()); // The Window //代碼片段二 var name2 = "The Window"; var object2 = { name2 : "My Object", getNameFunc : function(){ var that = this; return function(){ return that.name2; }; } }; alert(object2.getNameFunc()()); // My Object
面試題2:
function fun(n,o) { console.log(o) return { fun:function(m){ return fun(m,n) } } } var a = fun(0) a.fun(1) a.fun(2) a.fun(3)//undefined,0,0,0 var b = fun(0).fun(1).fun(2).fun(3)//undefined,0,1,2 var c = fun(0).fun(1) c.fun(2) c.fun(3)//undefined,0,1,1
可通過斷點調試查看執行步驟。
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://m.specialneedsforspecialkids.com/yun/105098.html
摘要:條件閉包是允許函數訪問局部作用域之外的數據。這就是需要理解閉包的核心內容。我們可以通過創建另一個匿名函數強制讓閉包的行為符合預期。而這個匿名函數內部又創建并返回了一個訪問的閉包。 showImg(https://segmentfault.com/img/remote/1460000009476113?w=500&h=222); 前言 有很多人搞不清匿名函數和閉包這兩個概念,經常混用。閉...
摘要:閉包與立即執行函數前言最近在細讀高級程序設計,對于我而言,中文版,書中很多地方翻譯的差強人意,所以用自己所理解的,嘗試解讀下。作用域鏈的這種配置機制引出了一個值得注意的副作用,即閉包只能取得包含任何變量的最后一個值。 閉包與立即執行函數 前言:最近在細讀Javascript高級程序設計,對于我而言,中文版,書中很多地方翻譯的差強人意,所以用自己所理解的,嘗試解讀下。如有紕漏或錯誤,會...
摘要:閉包閉包是指有權訪問另一個函數作用域中的變量的函數當某個函數被調用時,會創建一個執行環境及相應的作用域鏈。要注意通過第句聲明的這個方法屬于構造函數生成的對象,而不屬于構造函數的變量對象,也就是說,并不存在于作用域鏈中。 看到評論里有仁兄建議我試試箭頭函數,真是受寵若驚,本來寫這篇文章也只是想記錄寫要點給自己日后看的。今天早上看到一篇總結javascript中this的文章JavaScr...
摘要:分配這些變量的空間稱為堆棧空間,因為隨著函數的調用,它們的內存將被添加到現有內存之上。當函數調用其他函數時,每個函數在調用時都會獲得自己的堆棧塊。 該系列的第一篇文章重點介紹了引擎,運行時和調用堆棧的概述。第二篇文章深入剖析了Google的V8 JavaScript引擎,并提供了關于如何編寫更好的JavaScript代碼的一些提示。 在第三篇文章中,我們將討論另一個越來越被開發人員忽視...
閱讀 3898·2021-11-24 11:14
閱讀 3341·2021-11-22 13:53
閱讀 3905·2021-11-11 16:54
閱讀 1601·2021-10-13 09:49
閱讀 1238·2021-10-08 10:05
閱讀 3413·2021-09-22 15:57
閱讀 1768·2021-08-16 11:01
閱讀 985·2019-08-30 15:55