日韩av黄I国产麻豆传媒I国产91av视频在线观看I日韩一区二区三区在线看I美女国产在线I麻豆视频国产在线观看I成人黄色短片

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 前端技术 > HTML >内容正文

HTML

HTML5学习笔记(十八):闭包

發(fā)布時(shí)間:2025/7/14 HTML 75 豆豆
生活随笔 收集整理的這篇文章主要介紹了 HTML5学习笔记(十八):闭包 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

高階函數(shù)

JavaScript的函數(shù)其實(shí)都指向某個(gè)變量。既然變量可以指向函數(shù),函數(shù)的參數(shù)能接收變量,那么一個(gè)函數(shù)就可以接收另一個(gè)函數(shù)作為參數(shù),也可以返回一個(gè)函數(shù),這種函數(shù)就稱(chēng)之為高階函數(shù)。

函數(shù)作為參數(shù)

示例如下:

1 function absAdd(x, y, f) { 2 return f(x) + f(y); 3 } 4 console.log(absAdd(-1, 2, Math.abs)); // 3

函數(shù)作為參數(shù)的好處是我們可以通過(guò)修改參數(shù)就可以改變函數(shù)的行為。

函數(shù)作為返回值

示例如下:

1 function arrSum(arr) { 2 return function(){ 3 return arr.reduce(function (x, y) { 4 return x + y; 5 }); 6 }; 7 } 8 9 var f1 = arrSum([1, 2, 3, 4, 5]); 10 var f2 = arrSum([2, 4, 6, 8, 10]); 11 12 console.log(f1 === f2); // false 13 14 console.log(f1()); // 15 15 console.log(f2()); // 30

每次調(diào)用arrSum方法返回的都是一個(gè)新創(chuàng)建的函數(shù),所以判斷是不相等的。

返回函數(shù)時(shí),可以決定在何時(shí)執(zhí)行該函數(shù)。

閉包

我們注意到上面例子里返回的函數(shù)在其定義內(nèi)部引用了局部變量arr,所以,當(dāng)一個(gè)函數(shù)返回了一個(gè)函數(shù)后,其內(nèi)部的局部變量還被新函數(shù)引用,這種情況就稱(chēng)為閉包。

我們看下一個(gè)例子:

1 function foo() { 2 var r = []; 3 for (var i = 0; i < 3; i++) { 4 r[i] = function() { 5 return i; 6 }; 7 } 8 return r; 9 } 10 11 var arr = foo(); 12 for (var i = 0; i < 3; i++) { 13 console.log( arr[i]() ); 14 } 15 16 // 3 17 // 3 18 // 3

我們希望打印0,1,2這幾個(gè)數(shù)字,但是實(shí)際上打印的都是3,這是由于返回的函數(shù)保存的是變量i,實(shí)際上在循環(huán)之后變量i就變成了3,所以會(huì)出現(xiàn)這樣的情況。

立即執(zhí)行函數(shù)

那么如何才能打印出0,1,2這幾個(gè)數(shù)字呢,這里需要用到立即執(zhí)行函數(shù),立即執(zhí)行函數(shù)的意思是在定義好函數(shù)之后立即執(zhí)行,一般這樣的函數(shù)都是匿名函數(shù)。

格式如下:

1 (function (x) { 2 return x * x; 3 })(3);

即用一個(gè)括號(hào)將函數(shù)包含,后面緊跟另一個(gè)括號(hào)進(jìn)行調(diào)用,同時(shí)可以進(jìn)行參數(shù)傳遞。

我們?cè)倏聪旅娴睦?#xff1a;

1 function foo() { 2 var r = []; 3 for (var i = 0; i < 3; i++) { 4 r[i] = (function(index) { 5 return function() { 6 return index; 7 }; 8 })(i); 9 } 10 return r; 11 } 12 13 var arr = foo(); 14 for (var i = 0; i < 3; i++) { 15 console.log( arr[i]() ); 16 } 17 18 // 0 19 // 1 20 // 2

我們來(lái)看看這個(gè)例子,每個(gè)閉包函數(shù)實(shí)際上引用的是index參數(shù),而index參數(shù)是在立即執(zhí)行函數(shù)執(zhí)行時(shí)傳入的i,所以不存在改變的情況,就可以打印出對(duì)應(yīng)的索引值了。

關(guān)于this對(duì)象

我們來(lái)看下面的例子:

1 var name = "Window"; 2 3 var obj = { 4 name: "Object", 5 func: function() { 6 return function() { 7 return this.name; 8 }; 9 } 10 }; 11 12 console.log( obj.func()() ); // Window 13 14 var f = obj.func(); 15 console.log( f() ); // Window

我們發(fā)現(xiàn)返回的是全局的name屬性,而不是我們期望的obj的name屬性。

我們知道每個(gè)函數(shù)在調(diào)用時(shí)都會(huì)獲得this及arguments兩個(gè)參數(shù),而this參數(shù)指向調(diào)用該方法的對(duì)象。

所以我們可以看一下第14和15行,調(diào)用obj.func時(shí)this是指向obj對(duì)象的,返回的函數(shù)實(shí)際上被綁定到全局對(duì)象上了,所以當(dāng)調(diào)用f函數(shù)時(shí),實(shí)際上是window進(jìn)行調(diào)用的,所以拿到的name就是window.name。

解決方法如下:

1 var name = "Window"; 2 3 var obj = { 4 name: "Object", 5 func: function() { 6 var that = this; 7 return function() { 8 return that.name; 9 }; 10 } 11 }; 12 13 console.log( obj.func()() ); // Object 14 15 var f = obj.func(); 16 console.log( f() ); // Object

利用了閉包會(huì)持有調(diào)用鏈上的變量的原理即可。

私有屬性

在JavaScript中,沒(méi)有私有屬性的概念,所有屬性都是公開(kāi)的。

但是有私有變量的概念,在函數(shù)中聲明的變量,都是該函數(shù)私有的,函數(shù)以外的地方不能訪問(wèn)。

我們利用閉包和私有變量的特性可以創(chuàng)建出類(lèi)似于私有屬性的變量。

1 function Person(name) { 2 // 私有變量 3 var age = 0; 4 // 私有函數(shù) 5 function foo() { 6 console.log("call private function!"); 7 } 8 9 this.setName = function(value) { 10 name = value; 11 foo(); 12 }; 13 this.getName = function() { 14 return name; 15 }; 16 17 this.setAge = function(value) { 18 age = value; 19 foo(); 20 }; 21 this.getAge = function() { 22 return age; 23 }; 24 } 25 26 var p = new Person("Li Lei"); 27 p.age = 28; 28 console.log(p.getAge()); // 0 29 p.setAge(30); 30 console.log(p.getAge()); // 30 31 console.log(p.age); // 28

我們會(huì)發(fā)現(xiàn),在函數(shù)內(nèi)部是直接使用age來(lái)訪問(wèn)私有變量的,而如果是this.age則表示當(dāng)前對(duì)象的age公開(kāi)屬性,所以p.age和p.getAge會(huì)取得不同的數(shù)值。外部是無(wú)法訪問(wèn)到內(nèi)部變量age和參數(shù)name的。

使用立即執(zhí)行函數(shù)創(chuàng)建

我們發(fā)現(xiàn)上面的方法只能將所有代碼都寫(xiě)在構(gòu)造函數(shù)中才能訪問(wèn)到私有變量,其實(shí)還有一種寫(xiě)法:

1 (function(){ 2 // 使用 var 定義的變量外部無(wú)法訪問(wèn) 3 var _name; 4 var age = 0; 5 // 定義的函數(shù)外部無(wú)法訪問(wèn) 6 function foo() { 7 console.log("call private function!"); 8 } 9 10 // 不使用 var 定義的對(duì)象外部可訪問(wèn) 11 Person = function(name) { 12 _name = name; 13 } 14 15 Person.prototype.setName = function(value) { 16 _name = value; 17 foo(); 18 } 19 Person.prototype.getName = function() { 20 return _name; 21 } 22 23 Person.prototype.setAge = function(value) { 24 age = value; 25 foo(); 26 } 27 Person.prototype.getAge = function() { 28 return age; 29 } 30 })(); 31 32 var p = new Person("Li Lei"); 33 p.age = 28; 34 console.log(p.getAge()); // 0 35 p.setAge(30); 36 console.log(p.getAge()); // 30 37 console.log(p.age); // 28

通過(guò)一個(gè)立即執(zhí)行的匿名函數(shù)來(lái)包裹即可實(shí)現(xiàn)。

模塊模式

模塊模式可以實(shí)現(xiàn)對(duì)象的私有屬性和方法,如下:

1 var instance = function(){ 2 var name = "Han Meimei"; 3 4 function foo(){ 5 console.log("call private function"); 6 } 7 8 return { 9 setName: function(value) { 10 name = value; 11 foo(); 12 }, 13 getName: function() { 14 return name; 15 } 16 }; 17 }(); 18 19 instance.name = "Li Lei"; 20 console.log(instance.getName()); // Han Meimei 21 instance.setName("Uncle Wang"); 22 console.log(instance.getName()); // Uncle Wang 23 console.log(instance.name); // Li Lei

當(dāng)然,如果需要?jiǎng)?chuàng)建指定類(lèi)型的實(shí)例,可以使用下面的代碼:

1 var instance = function(){ 2 var name = "Han Meimei"; 3 4 function foo(){ 5 console.log("call private function"); 6 } 7 8 // 這里可以創(chuàng)建指定類(lèi)型的實(shí)例 9 var obj = new Object(); 10 11 // 添加方法 12 obj.setName = function(value) { 13 name = value; 14 foo(); 15 }; 16 obj.getName = function() { 17 return name; 18 }; 19 20 return obj; 21 }(); 22 23 instance.name = "Li Lei"; 24 console.log(instance.getName()); // Han Meimei 25 instance.setName("Uncle Wang"); 26 console.log(instance.getName()); // Uncle Wang 27 console.log(instance.name); // Li Lei

?

總結(jié)

以上是生活随笔為你收集整理的HTML5学习笔记(十八):闭包的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。