當前位置:
首頁 >
前端技术
> javascript
>内容正文
javascript
JS闭包的理解及常见应用场景
生活随笔
收集整理的這篇文章主要介紹了
JS闭包的理解及常见应用场景
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
JS閉包的理解及常見應用場景
一、總結
一句話總結:
閉包是指有權訪問另一個函數作用域中的變量的函數
?
1、如何從外部讀取函數內部的變量,為什么?
閉包:f2可以讀取f1中的變量,只要把f2作為返回值,就可以在f1外讀取f1內部變
原因:f1是f2的父函數,f2被賦給了一個全局變量,f2始終存在內存中,f2的存在依賴f1,因此f1也始終存在內存中,不會在調用結束后,被垃圾回收機制回收。
function f1(){var n = 123;function f2(){ //f2是一個閉包 alert(n)} return f2;}js鏈式作用域:子對象會一級一級向上尋找所有父對象的變量,反之不行。?
?
2、js鏈式作用域?
子對象會一級一級向上尋找所有父對象的變量,反之不行。
js中函數內部可以讀取全局變量,函數外部不能讀取函數內部的局部變量。
?
?
3、js變量兩種作用域?
全局變量、局部變量(函數內):js中函數內部可以讀取全局變量,函數外部不能讀取函數內部的局部變量。
?
?
4、閉包為什么可以實現在函數外讀取到函數內的變量?
|||-begin
function f1(){var n = 123;function f2(){ //f2是一個閉包 alert(n)} return f2;}|||-end
原因:f1是f2的父函數,f2被賦給了一個全局變量,f2始終存在內存中,f2的存在依賴f1,因此f1也始終存在內存中,不會在調用結束后,被垃圾回收機制回收。
?
?
?
二、對JS閉包的理解及常見應用場景
轉自或參考:對JS閉包的理解及常見應用場景
https://blog.csdn.net/qq_21132509/article/details/80694517
1、變量作用域
變量作用域兩種:全局變量、局部變量。js中函數內部可以讀取全局變量,函數外部不能讀取函數內部的局部變量。2、如何從外部讀取函數內部的變量?
function f1(){var n = 123;function f2(){ //f2是一個閉包alert(n)} return f2;} js鏈式作用域:子對象會一級一級向上尋找所有父對象的變量,反之不行。 f2可以讀取f1中的變量,只要把f2作為返回值,就可以在f1外讀取f1內部變量3、閉包概念
能夠讀取其他函數內部變量的函數。 或簡單理解為定義在一個函數內部的函數,內部函數持有外部函數內變量的引用。4、閉包用途
1、讀取函數內部的變量 2、讓這些變量的值始終保持在內存中。不會再f1調用后被自動清除。 3、方便調用上下文的局部變量。利于代碼封裝。 原因:f1是f2的父函數,f2被賦給了一個全局變量,f2始終存在內存中,f2的存在依賴f1,因此f1也始終存在內存中,不會在調用結束后,被垃圾回收機制回收。5、閉包理解
/*** [init description]* @return {[type]} [description]*/ function init() {var name = "Chrome"; //創建局部變量name和局部函數alertNamefunction alertName() { //alertName()是函數內部方法,是一個閉包alert(name); //使用了外部函數聲明的變量,內部函數可以訪問外部函數的變量}alertName(); } init(); //一個變量在源碼中聲明的位置作為它的作用域,同時嵌套的函數可以訪問到其外層作用域中聲明的變量/*** [outFun description]* @return {[type]} [description]*/ function outFun(){var name = "Chrome";function alertName(){alert(name);}return alertName; //alertName被外部函數作為返回值返回了,返回的是一個閉包 }var myFun = outFun(); myFun(); /* 閉包有函數+它的詞法環境;詞法環境指函數創建時可訪問的所有變量。 myFun引用了一個閉包,閉包由alertName()和閉包創建時存在的“Chrome”字符串組成。 alertName()持有了name的引用, myFunc持有了alertName()的的訪問, 因此myFunc調用時,name還是處于可以訪問的狀態。*//*** [add description]* @param {[type]} x [description]*/ function add(x){return function(y){return x + y;}; }var addFun1 = add(4); var addFun2 = add(9);console.log(addFun1(2)); //6 console.log(addFun2(2)); //11 //add接受一個參數x,返回一個函數,它的參數是y,返回x+y //add是一個函數工廠,傳入一個參數,就可以創建一個參數和其他參數求值的函數。 //addFun1和addFun2都是閉包。他們使用相同的函數定義,但詞法環境不同,addFun1中x是4,后者是56、閉包應用場景之setTimeout
//原生的setTimeout傳遞的第一個函數不能帶參數setTimeout(function(param){alert(param)},1000)//通過閉包可以實現傳參效果function func(param){return function(){alert(param)}}var f1 = func(1);setTimeout(f1,1000);7、閉包應用場景之回調
<!DOCTYPE html> <html> <head><meta charset="utf-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><title></title><link rel="stylesheet" href=""> </head> <style>body{font-size: 12px;}h1{font-size: 1.5rem;}h2{font-size: 1.2rem;} </style> <body><p>哈哈哈哈哈哈</p><h1>hhhhhhhhh</h1><h2>qqqqqqqqq</h2><a href="#" id="size-12">12</a><a href="#" id="size-14">14</a><a href="#" id="size-16">16</a><script>function changeSize(size){return function(){document.body.style.fontSize = size + 'px';};}var size12 = changeSize(12);var size14 = changeSize(14);var size16 = changeSize(16);document.getElementById('size-12').onclick = size12;document.getElementById('size-14').onclick = size14;document.getElementById('size-16').onclick = size16;//我們定義行為,然后把它關聯到某個用戶事件上(點擊或者按鍵)。我們的代碼通常會作為一個回調(事件觸發時調用的函數)綁定到事件上 </script> </body> </html>8、閉包應用場景之封裝變量
<!DOCTYPE html> <html> <head><meta charset="utf-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><title>閉包模擬私有方法</title><link rel="stylesheet" href=""> </head> <body> <script>//用閉包定義能訪問私有函數和私有變量的公有函數。var counter = (function(){var privateCounter = 0; //私有變量function change(val){privateCounter += val;}return {increment:function(){ //三個閉包共享一個詞法環境change(1);},decrement:function(){change(-1);},value:function(){return privateCounter;}};})();console.log(counter.value());//0counter.increment();counter.increment();//2//共享的環境創建在一個匿名函數體內,立即執行。//環境中有一個局部變量一個局部函數,通過匿名函數返回的對象的三個公共函數訪問。</script> </body> </html>9、閉包應用場景之為節點循環綁定click事件
<!DOCTYPE html> <html> <head><meta charset="utf-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><title></title><link rel="stylesheet" href=""> </head> <body><p id="info">123</p><p>E-mail: <input type="text" id="email" name="email"></p><p>Name: <input type="text" id="name" name="name"></p><p>Age: <input type="text" id="age" name="age"></p><script>function showContent(content){document.getElementById('info').innerHTML = content;};function setContent(){var infoArr = [{'id':'email','content':'your email address'},{'id':'name','content':'your name'},{'id':'age','content':'your age'}];for (var i = 0; i < infoArr.length; i++) {var item = infoArr[i];document.getElementById(item.id).onfocus = function(){showContent(item.content)}}}setContent()//循環中創建了三個閉包,他們使用了相同的詞法環境item,item.content是變化的變量//當onfocus執行時,item.content才確定,此時循環已經結束,三個閉包共享的item已經指向數組最后一項。/*** 解決方法1 通過函數工廠,則函數為每一個回調都創建一個新的詞法環境*/function showContent(content){document.getElementById('info').innerHTML = content;};function callBack(content){return function(){showContent(content)}};function setContent(){var infoArr = [{'id':'email','content':'your email address'},{'id':'name','content':'your name'},{'id':'age','content':'your age'}];for (var i = 0; i < infoArr.length; i++) {var item = infoArr[i];document.getElementById(item.id).onfocus = callBack(item.content)}}setContent()/*** 解決方法2 綁定事件放在立即執行函數中*/function showContent(content){document.getElementById('info').innerHTML = content;};function setContent(){var infoArr = [{'id':'email','content':'your email address'},{'id':'name','content':'your name'},{'id':'age','content':'your age'}];for (var i = 0; i < infoArr.length; i++) {(function(){var item = infoArr[i];document.getElementById(item.id).onfocus = function(){showContent(item.content)}})()//放立即執行函數,立即綁定,用每次的值綁定到事件上,而不是循環結束的值}}setContent()/*** 解決方案3 用ES6聲明,避免聲明提前,作用域只在當前塊內*/function showContent(content){document.getElementById('info').innerHTML = content;};function setContent(){var infoArr = [{'id':'email','content':'your email address'},{'id':'name','content':'your name'},{'id':'age','content':'your age'}];for (var i = 0; i < infoArr.length; i++) {let item = infoArr[i]; //限制作用域只在當前塊內document.getElementById(item.id).onfocus = function(){showContent(item.content)}}}setContent() </script> </body> </html>?
轉載于:https://www.cnblogs.com/Renyi-Fan/p/11590231.html
總結
以上是生活随笔為你收集整理的JS闭包的理解及常见应用场景的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: requireJS的基本使用
- 下一篇: js 函数定义的方式