摘要:閉包閉包是指有權(quán)訪問另一個(gè)函數(shù)作用域中的變量的函數(shù)。我們可以通過創(chuàng)建另一個(gè)匿名函數(shù)強(qiáng)制讓閉包的行為符合預(yù)期。不過,匿名函數(shù)的執(zhí)行環(huán)境具有全局性,因此其對(duì)象通常指向。
遞歸
function factorial(num){ if(num<=1){ return 1; }else { return num * arguments.callee(num-1); } } console.log(factorial(4));
但是如果代碼是在嚴(yán)格模式下開發(fā):
"use strict"; function factorial(num){ if(num<=1){ return 1; }else { return num * arguments.callee(num-1); } } console.log(factorial(4));
結(jié)果:Uncaught TypeError: "caller", "callee", and "arguments" properties may not be accessed on strict mode functions or the arguments objects for calls to them
在嚴(yán)格模式下不能通過腳本訪問arguments.callee,訪問這個(gè)屬性會(huì)報(bào)錯(cuò),那么可以使用命名函數(shù)表達(dá)式來(lái)達(dá)到相同的結(jié)果:
"use strict"; var factorial = (function f(num){ if(num<=1){ return 1; }else { return num * f(num-1); } }) console.log(factorial(4)); //24
以上代碼創(chuàng)建了一個(gè)名為f()的命名函數(shù)表達(dá)式,然后將它賦值給變量factorial,即是把函數(shù)賦值給另外一個(gè)變量,函數(shù)的名字仍然有效。
閉包閉包是指有權(quán)訪問另一個(gè)函數(shù)作用域中的變量的函數(shù)。
閉包與變量作用域鏈的這種配置機(jī)制引出了一個(gè)值得注意的副作用,即閉包只能取得包含函數(shù)中任何變量的最后一個(gè)值。別忘了閉包所保存的是整個(gè)變量對(duì)象,而不是某個(gè)特殊的變量。
function createFunctions(){ var result = new Array(); for (var i=0; i<10; i++){ result[i] = function(){ return i; } } return result; }
我們可以通過創(chuàng)建另一個(gè)匿名函數(shù)強(qiáng)制讓閉包的行為符合預(yù)期。
function createFunctions(){ var result = new Array(); for (var i=0; i<10; i++){ result[i] = function(num){ return function(){ return num; }; }(i); } return result; }關(guān)于this對(duì)象
在全局函數(shù)中,this等于window,而當(dāng)函數(shù)被作為某個(gè)對(duì)象的方法調(diào)用時(shí),this等于那個(gè)對(duì)象。不過,匿名函數(shù)的執(zhí)行環(huán)境具有全局性,因此其this對(duì)象通常指向window。
var name = "The window"; var object = { name: "My Object", getNameFunc: function(){ return function(){ return this.name; }; } }; console.log(object.getNameFunc()()); // The window
不過,把外部作用域中的this對(duì)象保存在一個(gè)閉包能夠訪問到的變量里,就可以讓閉包訪問該對(duì)象了。
var name = "The window"; var object = { name: "My Object", getNameFunc: function(){ var that = this; return function(){ return that.name; }; } }; console.log(object.getNameFunc()()); // My Object
看下面代碼:
var name = "The window"; var object = { name: "My Object", getName: function(){ console.log(this.name); } } object.getName(); // My Object (object.getName)(); // My Object (object.getName = object.getName)(); // The window
來(lái)分析下調(diào)用的結(jié)果:
第一行代碼跟平常一樣調(diào)用了object.getName()返回了My Object ,因?yàn)閠his.name就是object.name。
第二行代碼在調(diào)用這個(gè)方法之前給它加了一個(gè)括號(hào)。雖然加了一個(gè)括號(hào)后,就好像只是在引用一個(gè)函數(shù),但是this的值得到了維持,因?yàn)?b>object.getName和(object.getName)的定義是相同的。
第三行代碼先執(zhí)行了一條賦值語(yǔ)句,然后再調(diào)用賦值后的結(jié)果。因?yàn)檫@個(gè)賦值表達(dá)式的值是函數(shù)本身,所以this的值不能得到維持,結(jié)果就返回了The window。
當(dāng)然你不大可能像第二行和第三行代碼一樣調(diào)用這個(gè)方法。這個(gè)例子只是說明了一個(gè)細(xì)微的語(yǔ)法變化,都有可能意外的改變this的值。
內(nèi)存泄露function assignHandler(){ var element=document.getElementById("someElement"); element.onclick=function(){ alert(element.id); } }
上述代碼它所占用的內(nèi)存不會(huì)永遠(yuǎn)消失。修改一下代碼如下解決:
function assignHandler(){ var element = document.getElementById("someElement"); var id = element.id; element.onclick = function(){ alert(id); } element = null; }模仿塊級(jí)作用域
用塊級(jí)作用域(通常稱為私用作用域)的匿名函數(shù)的語(yǔ)法如下所示:
(function(){ })();私有變量
function add(num1,num2){ var sum=num1+num2; return sum; }
在這個(gè)函數(shù)內(nèi)部,有三個(gè)私有變量:sum,num1,num2。在函數(shù)內(nèi)部可以訪問這幾個(gè)變量。但是在函數(shù)外部則不能訪問它們。如果在這個(gè)函數(shù)內(nèi)部創(chuàng)建一個(gè)閉包,那么閉包可以通過自己的作用域鏈也可以訪問這些變量。而利用這一點(diǎn),就可以創(chuàng)建用于訪問私有變量的公有方法。
我們把有權(quán)訪問私有變量和私有函數(shù)的公有方法稱為特權(quán)方法。有兩種在對(duì)象上創(chuàng)建特權(quán)方法的方式。第一種是在構(gòu)造函數(shù)中定義特權(quán)方法?;灸J饺缦拢?/p>
function myObejct(){ //私有變量和私有函數(shù) var privateVariable=10; function privateFunction(){ return false; } //特權(quán)方法 this.publicMethod=function(){ privateVariable++; return privateFunction(); } }
利用私有和特權(quán)成員,可以隱藏那些不應(yīng)該被直接修改的數(shù)據(jù),例如:
function Person(name){ this.getName=function(){ return name; } this.setName=function(value){ name=value; } } var person=new Person("Nicholas"); alert(person.getName());//Nicholas person.setName("Greg"); alert(person.getName());//Greg靜態(tài)私有變量
通過在私有作用域中定義私有變量或函數(shù),同樣也可以創(chuàng)建特權(quán)方法。其基本模式如下:
(function(){ //私有變量和私有函數(shù) var privateVariable=10; function privateFunction(){ return false; } //構(gòu)造函數(shù) MyObject=function(){ }; //公有/特權(quán)方法 MyObject.prototype.publicMethod=function(){ privateVariable++; return privateFunction(); } })();
再看一個(gè)例子:
(function(){ var name = ""; Person = function(value){ name = value; }; Person.prototype.getName = function(){ return name; }; Person.prototype.setName = function(value){ name = value; }; })(); var person1 = new Person("Nicholas"); console.log(person1.getName()); //Nicholas person1.setName("Grey"); console.log(person1.getName()); //Grey var person2 = new Person("Michael"); console.log(person1.getName()); //Michael console.log(person2.getName()); //Michael
在一個(gè)實(shí)例上調(diào)用setName()會(huì)影響所有的實(shí)例。
模塊模式模塊模式是為單例創(chuàng)建私有變量和特權(quán)方法。所謂單例,指的就是只有一個(gè)實(shí)例的對(duì)象。按照慣例,js是以對(duì)象字面量的方式來(lái)創(chuàng)建單例對(duì)象的。
var singleton={ name:value, method:function(){ //這里是方法的代碼 } };
模塊模式通過為單例添加私有變量和特權(quán)方法能夠使其得到增強(qiáng)。其語(yǔ)法形式如下:
var singleton=function(){ //私有變量和私有函數(shù) var privateVariable=10; function privateFunction(){ return false; } //特權(quán)/公有屬性和方法 return { publicProperty:true, publicMethod:function(){ privateVariable++; return privateFunction(); } } }();增強(qiáng)的模塊模式
var singleton=function(){ //私有變量和私有函數(shù) var privateVariable=10; function privateFunction(){ return false; } //創(chuàng)建對(duì)象 var object=new CustomType(); //添加特權(quán)/公有屬性和方法 object.publicProperty=true; object.publicMethod=function(){ privateVariable++; return privateFunction(); } //返回這個(gè)對(duì)象 return object; }();
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/87646.html
摘要:網(wǎng)上有很多前端的學(xué)習(xí)路徑文章,大多是知識(shí)點(diǎn)羅列為主或是資料的匯總,數(shù)據(jù)量讓新人望而卻步。天了解一個(gè)前端框架。也可以關(guān)注微信公眾號(hào)曉舟報(bào)告,發(fā)送獲取資料,就能收到下載密碼,網(wǎng)盤地址在最下方,獲取教程和案例的資料。 前言 好的學(xué)習(xí)方法可以事半功倍,好的學(xué)習(xí)路徑可以指明前進(jìn)方向。這篇文章不僅要寫學(xué)習(xí)路徑,還要寫學(xué)習(xí)方法,還要發(fā)資料,干貨滿滿,準(zhǔn)備接招。 網(wǎng)上有很多前端的學(xué)習(xí)路徑文章,大多是知...
摘要:函數(shù)實(shí)際上是對(duì)象。所以需要消除這種緊耦合。函數(shù)內(nèi)部屬性引用的是函數(shù)據(jù)以執(zhí)行的環(huán)境對(duì)象或者也可以說是值函數(shù)的名字僅僅是一個(gè)包含指針的變量而已。因此,即使是在不同的環(huán)境中執(zhí)行,全局的函數(shù)與函數(shù)指向的仍然是同一個(gè)函數(shù)。 1.函數(shù)實(shí)際上是對(duì)象。每個(gè)函數(shù)都是 Function 類型的實(shí)例,而且都與其他引用類型一樣具有屬性和方法 2.由于函數(shù)名僅僅是指向函數(shù)的指針,因此函數(shù)名與包含對(duì)象指針的其他變...
摘要:學(xué)習(xí)筆記七數(shù)學(xué)形態(tài)學(xué)關(guān)注的是圖像中的形狀,它提供了一些方法用于檢測(cè)形狀和改變形狀。學(xué)習(xí)筆記十一尺度不變特征變換,簡(jiǎn)稱是圖像局部特征提取的現(xiàn)代方法基于區(qū)域圖像塊的分析。本文的目的是簡(jiǎn)明扼要地說明的編碼機(jī)制,并給出一些建議。 showImg(https://segmentfault.com/img/bVRJbz?w=900&h=385); 前言 開始之前,我們先來(lái)看這樣一個(gè)提問: pyth...
摘要:三種使用構(gòu)造函數(shù)創(chuàng)建對(duì)象的方法和的作用都是在某個(gè)特殊對(duì)象的作用域中調(diào)用函數(shù)。這種方式還支持向構(gòu)造函數(shù)傳遞參數(shù)。叫法上把函數(shù)叫做構(gòu)造函數(shù),其他無(wú)區(qū)別適用情境可以在特殊的情況下用來(lái)為對(duì)象創(chuàng)建構(gòu)造函數(shù)。 一、工廠模式 工廠模式:使用字面量和object構(gòu)造函數(shù)會(huì)有很多重復(fù)代碼,在此基礎(chǔ)上改進(jìn)showImg(https://segmentfault.com/img/bVbmKxb?w=456&...
閱讀 2305·2021-09-30 09:47
閱讀 2224·2021-09-26 09:55
閱讀 2954·2021-09-24 10:27
閱讀 1543·2019-08-27 10:54
閱讀 971·2019-08-26 13:40
閱讀 2500·2019-08-26 13:24
閱讀 2423·2019-08-26 13:22
閱讀 1735·2019-08-23 18:38