做用域是靜態的,在你寫代碼的時候就肯定了。javascript
執行上下文能夠理解爲當前代碼的執行環境,執行上下文是動態的,在執行調用的時候纔會產生。java
function fn1() {
//函數提高,內部函數已經建立。請看圖片1
var a = 1
function fn2() {
a++ ////代碼執行到這的時候,請看圖片3
console.log(a)
}
return fn2 //代碼執行到這的時候,請看圖片2
}
let fn3 = fn1()
fn3() //代碼執行到這的時候,請看圖片2
fn3 = null //閉包死亡
複製代碼
圖片1面試
function Pay(value) { //Pay是一個閉包
let money = value
this.getMoney = function() {
return money
}
this.setMoney = function(value) {
money = value
}
}
let pay = new Pay(8000)
console.log(pay.money) //undefined 在外面沒法訪問到私有變量money
console.log(pay.getMoney()) //8000 //getMoney這個特權方法能夠經過對象訪問,getMoney能夠訪問money
pay.setMoney(10000)
console.log(pay.getMoney()) //1000
複製代碼
function myModule() {
let msg = 'hello world' //私有數據
function doSomething() { //操做數據的函數
console.log('dosomething'+msg.toUpperCase())
}
function doOtherthing() {
console.log('doOtherthing'+msg.toLocaleLowerCase())
}
return{
doSomething:doSomething,
doOtherthing:doOtherthing
}
}
//模塊的使用者
let module = myModule()
module.doSomething()
module.doOtherthing()
複製代碼
for(var i=0;i<lis.length;i++) {
(function(i) {
setTimeout(() => {
alert(i)
}, 1000);
})(i)
}
複製代碼
function count() {
let num = 0
return function() { //函數做爲返回值
num++
return num
}
}
let fn = count()
fn() //1
複製代碼
function demo() {
let name = 'Eileen'
console.log('name')
}
demo() //demo函數執行完,demo函數的做用域沒有被外部引用,則該函數的做用域及其變量都會在函數執行完後被銷燬
複製代碼
function foo() {
let name = 'Eileen'
return function() {
name = 'John'
return name
}
}
let fn = foo()
console.log(fn()
fn = null //在全局做用域中執行fn函數,fn函數的環境依賴於foo函數環境,因此foo函數內的做用域及其變量不會被銷燬。fn = null釋放對閉包的引用,foo函數做用域被銷燬
複製代碼
function fun(n,o) {
console.log(o)
return {
fun: function(m) {
return fun(m,n)
}
}
}
var a = fun(0) //undefined
a.fun(1) //0
a.fun(2) //0
a.fun(3) //0
var b = fun(0).fun(1).fun(2).fun(3) //undefined,0,1,2
var c = fun(0).fun(1) //undefined,0
c.fun(2) //1
c.fun(3) //1
複製代碼
好啦,以上就是我對閉包的理解和解釋啦,若是有不對的地方,歡迎各位大牛指導一下😁bash