老司機帶你徹底搞懂JS閉包各種坑
##閉包是js發展慣用的技巧,什麼是閉包?
function outer() { var a = '变量1' var inner = function () { console.info(a) } return inner // inner 就是一个闭包函数,因为他能够访问到outer函数的作用域 }
#從堆疊的角度看待js函數
基本變量的值一般都是存在棧記憶體中,而物件類型的變數的值儲存在堆疊記憶體中,棧記憶體儲存對應空間位址。基本的資料型態: Number 、Boolean、Undefined、String、Null。var a = 1 //a是一个基本类型 var b = {m: 20 } //b是一个对象
var a = 1; function fn(){ var b = 2; function fn1(){ console.log(b); } fn1(); } fn();
function outer() { var a = '变量1' var inner = function () { console.info(a) } return inner // inner 就是一个闭包函数,因为他能够访问到outer函数的作用域 } var inner = outer() // 获得inner闭包函数 inner() //"变量1"
坑點1: 引用的變數可能改變
function outer() { var result = []; for (var i = 0; i<10; i++){ result.[i] = function () { console.info(i) } } return result }
function outer() { var result = []; for (var i = 0; i<10; i++){ result.[i] = function (num) { return function() { console.info(num); // 此时访问的num,是上层函数执行环境的num,数组有10个函数对象,每个对象的执行环境下的number都不一样 } }(i) } return result }
坑點2: this指向問題
var object = { name: ''object", getName: function() { return function() { console.info(this.name) } } } object.getName()() // underfined // 因为里面的闭包函数是在window作用域下执行的,也就是说,this指向window
坑點3:記憶體外洩問題
function showId() { var el = document.getElementById("app") el.onclick = function(){ aler(el.id) // 这样会导致闭包引用外层的el,当执行完showId后,el无法释放 } } // 改成下面 function showId() { var el = document.getElementById("app") var id = el.id el.onclick = function(){ aler(id) // 这样会导致闭包引用外层的el,当执行完showId后,el无法释放 } el = null // 主动释放el }
#技巧1: 用閉包解決遞歸呼叫問題
function factorial(num) { if(num<= 1) { return 1; } else { return num * factorial(num-1) } } var anotherFactorial = factorial factorial = null anotherFactorial(4) // 报错 ,因为最好是return num* arguments.callee(num-1),arguments.callee指向当前执行函数,但是在严格模式下不能使用该属性也会报错,所以借助闭包来实现 // 使用闭包实现递归 function newFactorial = (function f(num){ if(num<1) {return 1} else { return num* f(num-1) } }) //这样就没有问题了,实际上起作用的是闭包函数f,而不是外面的函数newFactorial
** 技巧2:用閉包模仿區塊級作用域**
es6沒出來之前,用var定義變數存在變數提升問題,eg:for(var i=0; i<10; i++){ console.info(i) } alert(i) // 变量提升,弹出10 //为了避免i的提升可以这样做 (function () { for(var i=0; i<10; i++){ console.info(i) } })() alert(i) // underfined 因为i随着闭包函数的退出,执行环境销毁,变量回收
JavaScript影片教學專欄!
以上是老司機帶你徹底搞懂JS閉包各種坑的詳細內容。更多資訊請關注PHP中文網其他相關文章!