首頁 web前端 js教程 一分鐘理解js閉包_javascript技巧

一分鐘理解js閉包_javascript技巧

May 16, 2016 pm 03:02 PM
js 閉包

什麼是閉包?
先看一段程式碼:

function a(){
  var n = 0;
  function inc() {
    n++;
    console.log(n);
  }
  inc(); 
  inc(); 
}
a(); //控制台输出1,再输出2
登入後複製

簡單吧。再來看一段程式碼:

function a(){
  var n = 0;
  this.inc = function () {
    n++; 
    console.log(n);
  };
}
var c = new a();
c.inc();  //控制台输出1
c.inc();  //控制台输出2
登入後複製

簡單吧。

什麼是閉包?這就是閉包!

有權存取另一個函數作用域內變數的函數都是閉包。這裡 inc 函數存取了建構函式 a 裡面的變數 n,所以形成了一個閉包。

再來看一段程式碼:

function a(){
  var n = 0;
  function inc(){
    n++; 
    console.log(n);
  }
  return inc;
}
var c = a();
c();  //控制台输出1
c();  //控制台输出2
登入後複製

看看是怎麼執行的:

var c = couter(),這一句 couter()回傳的是函數 inc,這句話等同於 var c = inc;

c(),這一句等同於 inc();  注意,函數名稱只是一個標識(指向函數的指標),而()才是執行函數。

後面三句翻譯過來就是:  var c = inc;  inc();  inc();,跟第一段程式碼有差嗎? 沒有。

什麼是閉包?這就是閉包!

所有的教科書教學都喜歡用最後一段來說明閉包,但我覺得這將問題複雜化了。這裡面回傳的是函數名,沒看過譚浩強C/C++程式設計的同學可能一下子沒反應出帶不帶()的差別,也就是說這種寫法自帶一個陷阱。雖然這種寫法更顯高大上,但我還是喜歡將問題單一化,看看代碼 1 和代碼 2,你還會糾結函數的調用,你會糾結 n 的值嗎?

為啥要這樣寫?
我們知道,js的每個函數都是一個小黑屋,它可以取得外界訊息,但是外界卻無法直接看到裡面的內容。將變數n 放進小黑屋裡,除了inc 函數之外,沒有其他辦法能接觸到變數n,而且在函數a 外定義同名的變數n 也是互不影響的,這就是所謂的增強“封裝性” 。

而之所以要用 return 返回函數來識別 inc,是因為在 a 函數外部無法直接呼叫 inc 函數,所以 return inc 與外部聯繫起來,代碼 2 中的 this 也是將 inc 與外部聯繫起來而已。

常見的陷阱
看看這個:

function createFunctions(){
  var result = new Array();
  for (var i=0; i < 10; i++){
    result[i] = function(){
      return i;
    };
  }
  return result;
}
var funcs = createFunctions();
for (var i=0; i < funcs.length; i++){
  console.log(funcs[i]());
}
登入後複製

乍一看,以為輸出 0~9 ,萬萬沒想到輸出10個10?

這裡的陷阱就是:函數帶()才是執行函數! 單純的一句 var f = function() { alert('Hi'); }; 是不會彈跳視窗的,後面接一句 f(); 才會執行函數內部的程式碼。上面程式碼翻譯一下就是:

var result = new Array(), i;
result[0] = function(){ return i; }; //没执行函数,函数内部不变,不能将函数内的i替换!
result[1] = function(){ return i; }; //没执行函数,函数内部不变,不能将函数内的i替换!
...
result[9] = function(){ return i; }; //没执行函数,函数内部不变,不能将函数内的i替换!
i = 10;
funcs = result;
result = null;

console.log(i); // funcs[0]()就是执行 return i 语句,就是返回10
console.log(i); // funcs[1]()就是执行 return i 语句,就是返回10
...
console.log(i); // funcs[9]()就是执行 return i 语句,就是返回10

登入後複製

為什麼只垃圾回收了 result,但卻不收了 i 呢? 因為 i 還在被 function 引用著啊。好比一個餐廳,盤子總是有限的,所以服務生會去巡台回收空盤子,但還裝著菜的盤子他怎麼敢收? 當然,你自己手動倒掉了盤子裡面的菜(=null),那盤子就會被收走了,這就是所謂的內存回收機制。

至於 i 的值怎麼還能保留,其實從文章開頭一路讀下來,這應該沒有什麼可以糾結的地方。盤子裡面的菜,吃了一塊不就該少一塊嗎?

總結
閉包就是一個函數引用另一個函數的變量,因為變數被引用所以不會被回收,因此可以用來封裝一個私有變數。這是優點也是缺點,不必要的閉包只會徒增記憶體消耗! 另外使用閉包也要注意變數的值是否符合你的要求,因為他就像一個靜態私有變數。閉包通常會跟很多東西混搭起來,接觸多了才能加深理解,這裡只是開個頭說說基礎性的東西。

本文連結:http://www.cnblogs.com/qieguo/p/5457040.html

以上就是本文的全部內容,希望對大家的學習有所幫助。

本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn

熱AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover

AI Clothes Remover

用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool

Undress AI Tool

免費脫衣圖片

Clothoff.io

Clothoff.io

AI脫衣器

AI Hentai Generator

AI Hentai Generator

免費產生 AI 無盡。

熱門文章

R.E.P.O.能量晶體解釋及其做什麼(黃色晶體)
3 週前 By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.最佳圖形設置
3 週前 By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.如果您聽不到任何人,如何修復音頻
3 週前 By 尊渡假赌尊渡假赌尊渡假赌
WWE 2K25:如何解鎖Myrise中的所有內容
4 週前 By 尊渡假赌尊渡假赌尊渡假赌

熱工具

記事本++7.3.1

記事本++7.3.1

好用且免費的程式碼編輯器

SublimeText3漢化版

SublimeText3漢化版

中文版,非常好用

禪工作室 13.0.1

禪工作室 13.0.1

強大的PHP整合開發環境

Dreamweaver CS6

Dreamweaver CS6

視覺化網頁開發工具

SublimeText3 Mac版

SublimeText3 Mac版

神級程式碼編輯軟體(SublimeText3)

建議:優秀JS開源人臉偵測辨識項目 建議:優秀JS開源人臉偵測辨識項目 Apr 03, 2024 am 11:55 AM

人臉偵測辨識技術已經是一個比較成熟且應用廣泛的技術。而目前最廣泛的網路應用語言非JS莫屬,在Web前端實現人臉偵測辨識相比後端的人臉辨識有優勢也有弱勢。優點包括減少網路互動、即時識別,大大縮短了使用者等待時間,提高了使用者體驗;弱勢是:受到模型大小限制,其中準確率也有限。如何在web端使用js實現人臉偵測呢?為了實現Web端人臉識別,需要熟悉相關的程式語言和技術,如JavaScript、HTML、CSS、WebRTC等。同時也需要掌握相關的電腦視覺和人工智慧技術。值得注意的是,由於Web端的計

C++ lambda 表達式中閉包的意思是什麼? C++ lambda 表達式中閉包的意思是什麼? Apr 17, 2024 pm 06:15 PM

在C++中,閉包是能夠存取外部變數的lambda表達式。若要建立閉包,請擷取lambda表達式中的外部變數。閉包提供可重複使用性、資訊隱藏和延遲求值等優點。它們在事件處理程序等實際情況中很有用,其中即使外部變數被銷毀,閉包仍然可以存取它們。

C++ Lambda 表達式如何實作閉包? C++ Lambda 表達式如何實作閉包? Jun 01, 2024 pm 05:50 PM

C++Lambda表達式支援閉包,即保存函數作用域變數並供函數存取。語法為[capture-list](parameters)->return-type{function-body}。 capture-list定義要捕獲的變量,可以使用[=]按值捕獲所有局部變量,[&]按引用捕獲所有局部變量,或[variable1,variable2,...]捕獲特定變量。 Lambda表達式只能存取捕獲的變量,但無法修改原始值。

C++ 函式中閉包的優點和缺點是什麼? C++ 函式中閉包的優點和缺點是什麼? Apr 25, 2024 pm 01:33 PM

閉包是一種巢狀函數,它能存取外層函數作用域的變量,優點包括資料封裝、狀態保持和靈活性。缺點包括記憶體消耗、效能影響和調試複雜性。此外,閉包還可以建立匿名函數,並將其作為回調或參數傳遞給其他函數。

解決閉包導致的記憶體洩漏問題 解決閉包導致的記憶體洩漏問題 Feb 18, 2024 pm 03:20 PM

標題:閉包造成的記憶體洩漏及解決方法引言:閉包是JavaScript中一個非常常見的概念,它可以讓內部函數存取外部函數的變數。然而,閉包在使用不當的情況下可能導致記憶體洩漏。本文將探討閉包所造成的記憶體洩漏問題,並提供解決方法及具體程式碼範例。一、閉包引起的記憶體洩漏問題閉包的特性是內部函數可以存取外部函數的變量,這意味著在閉包中引用的變數不會被垃圾回收。如果使用不當,

函數指標和閉包對Golang效能的影響 函數指標和閉包對Golang效能的影響 Apr 15, 2024 am 10:36 AM

函數指針和閉包對Go性能的影響如下:函數指針:稍慢於直接調用,但可提高可讀性和可復用性。閉包:通常更慢,但可封裝資料和行為。實戰案例:函數指標可最佳化排序演算法,閉包可建立事件處理程序,但會帶來效能損失。

js和vue的關係 js和vue的關係 Mar 11, 2024 pm 05:21 PM

js和vue的關係:1、JS作為Web開發基石;2、Vue.js作為前端框架的崛起;3、JS與Vue的互補關係;4、JS與Vue的實踐應用。

PHP 函數的鍊式呼叫與閉包 PHP 函數的鍊式呼叫與閉包 Apr 13, 2024 am 11:18 AM

是的,可以透過鍊式呼叫和閉包優化程式碼簡潔性和可讀性:鍊式呼叫可將函數呼叫連結為一個流暢介面。閉包可建立可重複使用程式碼區塊,並在函數外部存取變數。

See all articles