日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

闭包总结(2018.03.19)

發布時間:2023/12/31 编程问答 29 豆豆
生活随笔 收集整理的這篇文章主要介紹了 闭包总结(2018.03.19) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

什么是閉包?

簡單講,閉包就是指有權訪問另一個函數作用域中的變量的函數。

不好理解?看下面一個簡單的例子:

function func() {var a = 1, b = 2;function closure() {return a + b}return closure } 復制代碼

上述代碼中的closure就是一個閉包,是不是有點感覺了?

接下來再看下下面這句話:

通常,函數的作用域及其所有變量都會在函數執行結束后被銷毀。但是,在創建了一個閉包以后,這個函數的作用域就會一直保存到閉包不存在為止。

有點暈?我們一點點來看:

function addNum() {var a = 1, b = 2;console.log("addNum->a", a);console.log("addNum->b", b);return (a + b); }addNum(); console.log("handle->a", a); console.log("handle->b", b); 復制代碼

執行結果如上圖,在函數執行結束后,作用域和變量立即被銷毀。

如果有閉包存在:

function addNum(x) {return function(y) {return x + y;} }var handleAddNum = addNum(5); console.log(handleAddNum(2)); // 7 console.log(handleAddNum(3)); // 8 復制代碼

結果和上個例子是不是有所不同,按理說,addNum被執行結束后,x就應該別銷毀,但是因為有閉包的存在,x的作用域被繼續保留了,想要銷毀x,就要銷毀閉包。

handleAddNum = null; 復制代碼

下面在看下一個比較經典的閉包問題:

function test(){var arr = [];for(var i = 0;i < 10;i++){arr[i] = function(){return i;};}for(var a = 0;a < 10;a++){console.log(arr[a]());} } test(); //結果連打十個10 復制代碼

分析下執行過程:

首先,在這個作用域內,都是至上而下執行的,var i定義了一個整個作用域上的變量,第一個for語句執行結束后,i為10, 然后是第二個for語句,執行arr[i] = function(){ return i};,因為在函數中沒有找到i,會往上一層作用域去找,而上一層的i已經為10,所以會連續輸出十個十。

把var改動成let后,看下執行結果:

function test(){var arr = [];for(let i = 0;i < 10;i++){arr[i] = function(){return i;};}for(var a = 0;a < 10;a++){console.log(arr[a]());} } test(); //輸出0,1,2,3,4,5,6,7,8,9 復制代碼

分析下執行過程:

let 在定義變量時會開辟新的塊級作用域,即每次for循環都會開辟出一塊的新的作用域,所以當執行arr[i] = function(){ return i};時,沒有找到i時,向上找,在let開辟的新的塊級作用域中找到了i,即對應的0,1,2,3,4,5,6,7,8,9

閉包中的this對象:

有如下代碼:

var obj = {name: 'yy',getThis: function() {console.log('this', this);} }obj.getThis(); 復制代碼

執行結果:this Object {name: "yy"}...就是我們普遍認為的函數在哪里定義就在哪里執行。

那再看下面這個例子:

var obj = {name: 'yy',getThis: function() {//匿名函數return function() {console.log('this', this);}} } obj.getThis()(); 復制代碼

執行結果:

this Window {speechSynthesis: SpeechSynthesis, caches: CacheStorage, localStorage: Storage, sessionStorage: Storage, webkitStorageInfo: DeprecatedStorageInfo…}

全局作用域中調用了匿名函數,所以this指向了window。

不要認為函數在哪里,其內部的this就指向哪里。匿名函數的執行環境具有全局性,因此其 this 對象通常指向 window。

鞏固下,想想下面的結果是啥:

var name = "The Window";var obj = {name: "My Object",getName: function(){var that = this;console.log('getName:', this);return function(){return that.name;};} };console.log(obj.getName()()); 復制代碼

閉包的應用:設計私有的方法和變量

  • 任何在函數中定義的變量,都可以認為是私有變量,因為不能在函數外部訪問這些變量。私有變量包括函數的參數、局部變量和函數內定義的其他函數。
  • 把有權訪問私有變量的公有方法稱為特權方法(privileged method)。
function Animal(){// 私有變量var series = "哺乳動物";function run(){console.log("Run!!!");}// 特權方法this.getSeries = function(){return series;}; } 復制代碼

單例(singleton):指的是只有一個實例的對象。JavaScript 一般以對象字面量的方式來創建一個單例對象。

var singleton = {name: "percy",speak:function(){console.log("speaking!!!");},getName: function(){return this.name;} }; 復制代碼

模塊模式(The Module Pattern):為單例創建私有變量和方法。

var singleton = (function(){// 私有變量var age = 22;var speak = function(){console.log("speaking!!!");};// 特權(或公有)屬性和方法return {name: "percy",getAge: function(){return age;}}; })(); 復制代碼

閉包的缺陷:

  • 閉包的缺點就是常駐內存會增大內存使用量,并且使用不當很容易造成內存泄露。
  • 如果不是因為某些特殊任務而需要閉包,在沒有必要的情況下,在其它函數中創建函數是不明智的,因為閉包對腳本性能具有負面影響,包括處理速度和內存消耗。
  • 總結

    以上是生活随笔為你收集整理的闭包总结(2018.03.19)的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。