摘要:閉包,獲取一個局部作用域里變量的訪問權限,涉及到作用域棧執(zhí)行上下文垃圾回收機制內存駐留以及性能問題,閉包切斷作用域棧產(chǎn)生的垃圾回收事件,實現(xiàn)變量的內存駐留。因而,為避免產(chǎn)生嚴重的性能問題,在完成事件任務后要把閉包置為,釋放內存。
閉包,獲取一個局部作用域里變量的訪問權限,涉及到作用域棧、執(zhí)行上下文、垃圾回收機制、內存駐留以及性能問題,閉包切斷作用域棧產(chǎn)生的垃圾回收事件,實現(xiàn)變量的內存駐留。主要應用場景在需要累積效應、重復循環(huán)事件、前后事件相關等。因而,為避免產(chǎn)生嚴重的性能問題,在完成事件任務后要把閉包置為null,釋放內存。
這里介紹JS中作用域棧的特性,即先進后出,全局作用域位于棧底,局部作用域按照編譯、執(zhí)行順序依次入棧,執(zhí)行完畢依次出棧,對變量進行垃圾回收,釋放內存。了解此特性,利用全局作用域始終位于棧底,并且總是最后完成垃圾回收,只要在局部作用域中裝載具有全局效應的作用域,阻斷垃圾回收,就完成了閉包的設計。
示例1
function foo(x) { var tmp = 3; return function (y) { console.log(x + y + tmp); x.memb = x.memb ? x.memb + 1 : 1; console.log(x.memb); } } var age = new Number(2); var bar = foo(age); // bar 現(xiàn)在是一個引用了age的閉包 bar(10);
示例2
function foo(x) { var temp = 3; return function (y) { console.log(x + y + (++temp)); } } var bar = foo(2); bar(10);
示例3
function badClosureExample() { var as = document.querySelectorAll("a"); for (var i = 0; i < 4; i++) { as[i].onclick = new popNum(i); function popNum(oNum) { return function () { alert("單擊第" + oNum + "個"); } } } } badClosureExample();
示例4
function badClosureExample() { var as = document.querySelectorAll("a"); for (var i = 0; i < 4; i++) { (function (i) { as[i].onclick = function () { alert("單擊第" + i + "個"); } })(i); } } badClosureExample();
1、將變量 i 保存給在每個段落對象(p)上
function init() { var pAry = document.getElementsByTagName("p"); for (var i = 0; i < pAry.length; i++) { pAry[i].i = i; pAry[i].onclick = function () { alert(this.i); } } } init();
2、將變量 i 保存在匿名函數(shù)自身
function init() { var pAry = document.getElementsByTagName("p"); for (var i = 0; i < pAry.length; i++) { (pAry[i].onclick = function () { alert(arguments.callee.i); }).i = i; } } init();
3、加一層閉包,i 以函數(shù)參數(shù)形式傳遞給內層函數(shù)
function init() { var pAry = document.getElementsByTagName("p"); for (var i = 0; i < pAry.length; i++) { (function (i) { pAry[i].onclick = function () { alert(i); } })(i);//調用時參數(shù) } } init();
4、加一層閉包,i 以局部變量形式傳遞給內層函數(shù)
function init() { var pAry = document.getElementsByTagName("p"); for (var i = 0; i < pAry.length; i++) { (function () { var index = i;//調用時局部變量 pAry[i].onclick = function () { alert(index); } })(); } } init();
5、加一層閉包,返回一個函數(shù)作為響應事件(注意與3的細微區(qū)別)
function init() { var pAry = document.getElementsByTagName("p"); for (var i = 0; i < pAry.length; i++) { pAry[i].onclick = function (i) { return function () { //返回一個函數(shù) alert(i); } }(i) } } init();
6、用Function實現(xiàn),實際上每產(chǎn)生一個函數(shù)實例就會產(chǎn)生一個閉包
function init() { var pAry = document.getElementsByTagName("p"); for (var i = 0; i < pAry.length; i++) { pAry[i].onclick = new Function("alert(" + i + ")"); //new一次就產(chǎn)生一個函數(shù)實例 } } init();
7、用Function實現(xiàn),注意與6的區(qū)別
function init() { var pAry = document.getElementsByTagName("p"); for (var i = 0; i < pAry.length; i++) { pAry[i].onclick =Function("alert(" + i + ")"); } } init();
示例5
var name = "The Window"; var object = { name: "My Object", getNameFunc: function () { return function () { return this.name; }; } }; alert(object.getNameFunc()()); //The Window
示例6
function outerFun() { var a = 0; function innerFun() { a++; alert(a); } return innerFun; //注意這里 } var obj = outerFun(); obj(); //結果為1 obj(); //結果為2
文章版權歸作者所有,未經(jīng)允許請勿轉載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉載請注明本文地址:http://m.hztianpu.com/yun/82405.html
摘要:大名鼎鼎的閉包面試必問。閉包的作用是什么。看到閉包在哪了嗎閉包到底是什么五年前,我也被這個問題困擾,于是去搜了并總結下來。關于閉包的謠言閉包會造成內存泄露錯。閉包里面的變量明明就是我們需要的變量,憑什么說是內存泄露這個謠言是如何來的因為。 本文為饑人谷講師方方原創(chuàng)文章,首發(fā)于 前端學習指南。 大名鼎鼎的閉包!面試必問。請用自己的話簡述 什么是「閉包」。 「閉包」的作用是什么。 首先...
摘要:完美的閉包,對,閉包就這么簡單。這僅僅是閉包的一部分,閉包利用函數(shù)作用域達到了訪問外層變量的目的。此時一個完整的閉包實現(xiàn)了,的垃圾回收機制由于閉包的存在無法銷毀變量。 1.閉包是指有權訪問另一個函數(shù)作用域中的變量的函數(shù)。 上面這段話來自 javascript 高級程序設計 第三版 P178 。作者說閉包是一個函數(shù),它有訪問另一個函數(shù)作用域中的變量的能力。 2.函數(shù)訪問它被創(chuàng)建時所處的...
摘要:到底什么是閉包這個問題在面試是時候經(jīng)常都會被問,很多小白一聽就懵逼了,不知道如何回答好。上面這么說閉包是一種特殊的對象。閉包的注意事項通常,函數(shù)的作用域及其所有變量都會在函數(shù)執(zhí)行結束后被銷毀。從而使用閉包模塊化代碼,減少全局變量的污染。 閉包,有人說它是一種設計理念,有人說所有的函數(shù)都是閉包。到底什么是閉包?這個問題在面試是時候經(jīng)常都會被問,很多小白一聽就懵逼了,不知道如何回答好。這個...
閱讀 1536·2021-11-11 16:54
閱讀 10060·2021-11-02 14:44
閱讀 2453·2021-10-22 09:53
閱讀 3334·2019-08-30 11:18
閱讀 2029·2019-08-29 13:29
閱讀 2096·2019-08-27 10:58
閱讀 1724·2019-08-26 11:38
閱讀 3603·2019-08-26 10:31