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