es6有閉包。在es6中,在一個函數內部建立另一個函數,把內嵌的函數稱為閉包,它可以存取外部函數的區域性變數;簡單來說,閉包指有權存取另一個函數作用域中變數的函數。閉包的主要作用:延伸了變數的作用範圍。由於閉包會使得函數中的變數都被儲存在記憶體中,記憶體消耗很大,所以不能濫用閉包,否則會造成網頁的效能問題,在IE中可能導致記憶體洩露。
前端(vue)入門到精通課程:進入學習
Apipost = Postman + Swagger + Mock + Jmeter 超好用的API偵錯工具:
本教學操作環境:windows7系統、ECMAScript 6版、Dell G3電腦。
變數根據作用域的不同分為兩種:全域性變數和區域性變數。
函數內部可以使用全域性變數。
函數外部不可以使用區域性變數。
當函數執行完畢,本作用域內的區域性變數會銷燬。
在es6中,閉包(closure)指有權存取另一個函數作用域中變數的函數。簡單理解:一個作用域可以存取另外一個函數內部的區域性變數。
閉包:在一個函數內部建立另一個函數,把內嵌的函數稱為閉包,它可以存取外部函數的區域性變數
// fun 這個函數作用域 存取了另外一個函數 fn 裡面的區域性變數 num
function fn(){
let num = 10
function fun(){
console.log(num)
}
fun()
}
fn() //10
登入後複製
閉包的主要作用:延伸了變數的作用範圍。
// fn 外面的作用域可以存取fn 內部的區域性變數
function fn(){
let num = 10
// 方法一: 先定義再返回函數
function fun(){
console.log(num)
}
return fun //返回 fun函數
}
let f = fn()
f() //10
登入後複製
// fn 外面的作用域可以存取fn 內部的區域性變數
function fn(){
let num = 10
// 方法二: 直接返回函數
return function(){
console.log(num)
}
}
let f = fn()
f() //10
登入後複製
(1)用來返回值
//以閉包的形式將 name 返回
function fun(){
let name = 'woniu'
//定義閉包
return function f1(){
return name
}
}
let ft = fun() //因為fun函數的返回值是f1函數,ft實質是一個函數
let na = ft() //呼叫ft函數,實際呼叫的就是f1函數
console.log(na); //woniu
登入後複製
(2)函數賦值:在函數內部定義函數表示式
var f2
function fn(){
let name = '曹操'
f2 = function(){ //閉包,將外部函數的name變數作為閉包的返回值
return name
}
}
fn() //必須先呼叫fn函數,否則f2不是一個函數
console.log(f2()); //曹操
登入後複製
(3)把閉包作為函數的引數
function fn(){
let name = '蝸牛學苑'
//定義閉包
return function callback(){
return name
}
}
let f1 = fn() //將fn函數的返回值callback賦給f1
function f2(temp){
console.log(temp()) //輸出temp函數的返回值,實際呼叫了閉包callback
}
//呼叫f2函數:將f1作為實參傳遞給temp
f2(f1)
登入後複製
(4)立即執行函數中使用閉包
//立即執行函數
(function(){
let name = '蝸牛學苑'
let f1 = function(){
return name
}
fn2(f1) //呼叫fn2函數,將閉包f1作為實參傳遞給fn2函數
})()
function fn2(temp){ //temp是一個形參,接收f1
console.log(temp()); //對temp的呼叫,實際呼叫的是閉包f1
}
登入後複製
(5)迴圈賦值
(function(){
for (let i = 1; i <= 10; i++) {
(
function(j){
setTimeout(function(){
console.log(j);
},j*1000)
}
)(i)
}
})()
登入後複製
(6)將閉包封裝到物件中
function fun(){
let name = '蝸牛學苑'
setName = function(na){ //setName是閉包,用來設定外部函數的變數值
name = na
}
getName = function(){ //getName是閉包,用來返回外部函數的變數值
return name
}
//外部fun函數的返回值,將閉包封裝到物件中返回
return {
setUserName:setName,
getUserName:getName
}
}
let obj =fun() //將fun函數返回值(物件)賦給obj
console.log('使用者名稱:',obj.getUserName()) //蝸牛學苑
obj.setUserName('石油學苑')
console.log('使用者名稱:',obj.getUserName()) //石油學苑
登入後複製
(7)通過閉包實現迭代
let arr = ['aa','bb','cc']
function fn(temp){ //外部函數的返回值是閉包
let i = 0
//定義閉包:迭代獲取陣列元素並返回
return function(){
return temp[i++] || '陣列已經遍歷結束'
}
}
let f1 = fn(arr)
console.log(f1()) //aa
console.log(f1()) //bb
console.log(f1()) //cc
console.log(f1()) //陣列已經遍歷結束
登入後複製
(8)、首次區分(相同的引數,函數不會重複執行)
var fn = (function(){
var arr = [] //用來快取的陣列
return function(val){
if(arr.indexOf(val) == -1){ //快取中沒有則表示需要執行
arr.push(val) //將引數push到快取陣列中
console.log('函數被執行了',arr); //這裡寫想要執行的函數
} else {
console.log('此次函數不需要執行');
}
console.log('函數呼叫完列印一下,方便檢視快取的陣列:',arr);
}
})()
fn(10)
fn(10)
fn(1000)
fn(20)
fn(1000)
登入後複製
注意
(1)搞清除誰是閉包函數
(2)分清楚閉包的返回值、外部函數的返回值
閉包是什麼:閉包是一個函數(一個作用域可以存取另外一個函數的區域性變數)。
閉包的作用是什麼:延伸變數的作用範圍。
沒有產生閉包,因為並沒有區域性變數,所以存取到的是全域性變數
The Window
let name = 'The Window'
let object = {
name: 'My Object',
getNameFunc(){
return function(){
return this.name
}
}
}
let f = object.getNameFunc()
console.log(f()) //The Window
登入後複製
產生了閉包:因為 this 在函數內部被賦值給了 that,指向的是 object 這個物件。
let name = 'The Window'
let object = {
name: 'My Object',
getNameFunc(){
let that = this
return function(){
return that.name
}
}
}
let f = object.getNameFunc()
console.log(f()) //My Object
登入後複製
使用閉包的注意點
1)由於閉包會使得函數中的變數都被儲存在記憶體中,記憶體消耗很大,所以不能濫用閉包,否則會造成網頁的效能問題,在IE中可能導致記憶體洩露。解決方法是,在退出函數之前,將不使用的區域性變數全部刪除。
2)閉包會在父函數外部,改變父函數內部變數的值。所以,如果你把父函數當作物件(object)使用,把閉包當作它的公用方法(Public Method),把內部變數當作它的私有屬性(private value),這時一定要小心,不要隨便改變父函數內部變數的值。
【推薦學習:】
以上就是es6有閉包嗎的詳細內容,更多請關注TW511.COM其它相關文章!