詳解JavaScript的閉包、IIFE、apply、函數(shù)與對象
目錄
一、閉包(Closure)
1.1、閉包相關(guān)的問題
1.2、理解閉包
二、對象
2.1、對象常量(字面量)
2.2、取值
2.3、枚舉(遍歷)
2.4、更新與添加
2.5、對象的原型
2.6、刪除
2.7、封裝
三、函數(shù)
3.1、參數(shù)對象 (arguments)
3.2、構(gòu)造函數(shù)
3.3、函數(shù)調(diào)用
3.3.1、call
3.3.2、apply
3.3.3、caller
3.3.4、Callee
3.5、立即執(zhí)行函數(shù)表達(dá)式 (IIFE)
3.5.1、匿名函數(shù)與匿名對象
3.5.2、函數(shù)與函數(shù)表達(dá)式
3.5.3、立即執(zhí)行函數(shù)表達(dá)式與匿名對象
3.5.4、各種IIFE的寫法
3.5.5、參數(shù)
3.5.6、添加分號
3.5.7、IIFE的作用
3.5.8、IIFE的變形
四、示例下載
一、閉包(Closure)
1.1、閉包相關(guān)的問題
請在頁面中放10個div,每個div中放入字母a-j,當(dāng)點(diǎn)擊每一個div時顯示索引號,如第1個div顯示0,第10個顯示9;方法:找到所有的div,for循環(huán)綁定事件。
示例代碼:
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>閉包</title> <style type="text/css"> div { width: 100px; height: 100px; background: lightgreen; float: left; margin: 20px; font: 30px/100px "microsoft yahei"; text-align: center; } </style> </head> <body> <div>a</div> <div>b</div> <div>c</div> <div>d</div> <div>e</div> <div>f</div> <div>g</div> <div>h</div> <div>i</div> <div>j</div> <script type="text/javascript"> var divs=document.getElementsByTagName("div"); for (var i=0;i<divs.length;i++) { divs[i].onclick=function(){ alert(i); } } </script> </body> </html>
運(yùn)行結(jié)果:
因為點(diǎn)擊事件的函數(shù)內(nèi)部使用外部的變量i一直在變化,當(dāng)我們指定click事件時并沒有保存i的副本,這樣做也是為了提高性能,但達(dá)不到我們的目的,我們要讓他執(zhí)行的上下文保存i的副本,這種機(jī)制就是閉包。
修改后的代碼:
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>閉包</title> <style type="text/css"> div { width: 100px; height: 100px; background: lightgreen; float: left; margin: 20px; font: 30px/100px "microsoft yahei"; text-align: center; } </style> </head> <body> <div>a</div> <div>b</div> <div>c</div> <div>d</div> <div>e</div> <div>f</div> <div>g</div> <div>h</div> <div>i</div> <div>j</div> <script type="text/javascript"> var divs=document.getElementsByTagName("div"); for (var i=0;i<divs.length;i++) { divs[i].onclick=(function(n){ return function(){ alert(n); } })(i); } </script> </body> </html>
運(yùn)行結(jié)果:
n是外部函數(shù)的值,但是內(nèi)部函數(shù)(點(diǎn)擊事件)需要使用,返回函數(shù)前的n被臨時駐留在內(nèi)存中給點(diǎn)擊事件使用,簡單說就是函數(shù)的執(zhí)行上下文被保存起來,i生成了多個副本。
1.2、理解閉包
閉包概念:當(dāng)一個內(nèi)部函數(shù)被調(diào)用,就會形成閉包,閉包就是能夠讀取其他函數(shù)內(nèi)部變量的函數(shù),定義在一個函數(shù)內(nèi)部的函,創(chuàng)建一個閉包環(huán)境,讓返回的這個子程序抓住i,以便在后續(xù)執(zhí)行時可以保持對這個i的引用。內(nèi)部函數(shù)比外部函數(shù)有更長的生命周期;函數(shù)可以訪問它被創(chuàng)建時所處的上下文環(huán)境。
Javascript語言特有的"鏈?zhǔn)阶饔糜?結(jié)構(gòu)(chain scope),子對象會一級一級地向上尋找所有父對象的變量
二、對象
對象就是“鍵/值”對的集合并擁有一個連接到原型(prototype)對隱藏連接。
2.1、對象常量(字面量)
一個對象字面量就是包含在一對花括號中的零個或多個“鍵/值”對。對象字面量可以出現(xiàn)在任何允許表達(dá)式出現(xiàn)的地方。
對象的定義:
//空對象 var obj1={}; //對象中的屬性 var obj2={name:"foo",age:19}; var obj3={"nick name":"dog"}; //對象中的方法 var obj4={ price:99, inc:function(){ this.price+=1; } }
對象中可包含的內(nèi)容:
對象常量可以出現(xiàn)在任何允許表達(dá)式出現(xiàn)的地方,對象、數(shù)組、函數(shù)可以相互間嵌套,形式可以多種多樣。對象的值可以是:數(shù)組,函數(shù),對象,基本數(shù)據(jù)類型等。
//對象中可包含的內(nèi)容 var obj5 = [{ name: "jack" }, { name: "lucy", //常量 hobby:["讀書","上網(wǎng)","代碼"], //數(shù)組 friend:{name:"mark",height:198,friend:{}}, //對象 show:function(){ //函數(shù) console.log("大家好,我是"+this.name); } }]; //對象中的this是動態(tài)的,指向的是:調(diào)用者 obj5[1].show();
輸出:大家好,我是lucy
2.2、取值
方法一:直接使用點(diǎn)號運(yùn)算
//3取值 var obj6={"nick name":"pig",realname:"Rose"}; console.log(obj6.realname); //console.log(obj6.nick name); 錯誤
方法二:使用索引器,當(dāng)對象中的key有空格是
//3取值 var obj6={"nick name":"pig",realname:"Rose"}; console.log(obj6["realname"]); console.log(obj6["nick name"]);
2.3、枚舉(遍歷)
方法一:
var obj7={weight:"55Kg","nick name":"pig",realname:"Rose"}; for (var key in obj7) { console.log(key+":"+obj7[key]); }
運(yùn)行結(jié)果:
輸出順序是不能保證的。
2.4、更新與添加
如果對象中存在屬性就修改對應(yīng)值,如果不存在就添加。對象通過引用傳遞,它們永遠(yuǎn)不會被復(fù)制
var obj8={realname:"King"}; obj8.realname="Queen"; //修改 obj8.weight=1000; //添加屬性 obj8.show=function() //添加方法 { console.log(this.realname+","+this.weight); } obj8.show();
輸出:
Queen,1000
var obj8={realname:"King"}; obj8.realname="Queen"; //修改 obj8.weight=1000; //添加屬性 obj8.show=function() //添加方法 { console.log(this.realname+","+this.weight); } obj8.show(); //引用 var obj9=obj8; //obj9指向obj8的引用 obj9.realname="Jack"; obj8.show();
輸出:
2.5、對象的原型
javascript是一種動態(tài)語言,與C#和Java這樣的靜態(tài)語言是不一樣的;javascript并沒有嚴(yán)格的類型,可以簡單認(rèn)為javascript是由對象組成的,對象間連接到原型(prototype)實現(xiàn)功能的擴(kuò)展與繼承。每個對象都鏈接到一個原型對象,并且可以從中繼承屬性,所有通過常量(字面量)創(chuàng)建的對象都連接到Object.prototype,它是JavaScript中的頂級(標(biāo)配)對象,類似高級語言中的根類。
現(xiàn)在我們修改系統(tǒng)中的Object對象,添加一個創(chuàng)建方法,指定要創(chuàng)建對象的原型,實現(xiàn)類似繼承功能:
<script type="text/javascript"> if(typeof Object.beget !== "function") { Object.create = function(o) { //構(gòu)造函數(shù),用于創(chuàng)建對象 var F = function() {}; //指定由構(gòu)造函數(shù)創(chuàng)建的對象的原型 F.prototype = o; //調(diào)用構(gòu)造方法創(chuàng)建新對象 return new F(); } } var rose={ name:"rose", show:function(){ console.log("姓名:"+this.name); } }; rose.show(); //輸出 var lucy=Object.create(rose); //簡單認(rèn)為是:創(chuàng)建一個對象且繼承rose lucy.name="lucy"; //重寫 lucy.show(); </script>
運(yùn)行結(jié)果:
原型關(guān)系是一種動態(tài)關(guān)系,如果修改原型,該原型創(chuàng)建的對象會受到影響。
var lucy=Object.create(rose); //簡單認(rèn)為是:創(chuàng)建一個對象且繼承rose lucy.name="lucy"; //重寫 var jack=Object.create(rose); jack.name="jack"; //修改原型中的方法 rose.show=function(){ console.log("姓名->"+this.name); } lucy.show(); jack.show();
結(jié)果:
關(guān)于原型在函數(shù)中會再講到。
2.6、刪除
//刪除屬性 delete mark.name; //調(diào)用方法,輸出:姓名:undefined mark.show(); //刪除函數(shù) delete mark.show; //錯誤,mark.show is not a function mark.show();
刪除不用的屬性是一個好習(xí)慣,在某些情況下可能引發(fā)內(nèi)存泄漏。
2.7、封裝
使用對象封裝的好處是可以減少全局變量的污染機(jī)會,將屬性,函數(shù)都隸屬一個對象。
封裝前:
var name="foo"; //name是全局的,被暴露 i=1; //全局的,沒有var關(guān)鍵字聲明的變量是全局的,與位置關(guān)系不大 function show(){ //show 是全局的,被暴露 console.log("name->"+name); console.log(++i); } //i是全局的 2 show(); //3 show();
封裝后:
//對外只暴露bar,使用閉包封裝 var bar=function(){ var i=1; return{ name:"bar", show:function(){ console.log("name->"+this.name); console.log(++i); } }; }; var bar1=bar(); //2 bar1.show(); //3 bar1.show(); var bar2=bar(); //2,因為被封裝,且閉包,i是局部私有的 bar2.show();
運(yùn)行結(jié)果:
三、函數(shù)
javascript中的函數(shù)就是對象,對象就是“鍵/值”對的集合并擁有一個連接到原型對隱藏連接。
3.1、參數(shù)對象 (arguments)
第一個函數(shù)中有一個默認(rèn)對象叫arguments,類似數(shù)組,但不是數(shù)組,該對象是傳遞給函數(shù)的參數(shù)。
<script type="text/javascript"> function counter(){ var sum=0; for(var i=0;i<arguments.length;i++){ sum+=arguments[i]; } return sum; } console.log(counter(199,991,1,2,3,4,5)); console.log(counter()); </script>
運(yùn)行結(jié)果:
1205
0
這里的arguments是一個隱式對象,不聲明也在函數(shù)中,內(nèi)部函數(shù)可以訪問外部函數(shù)的任意內(nèi)容,但是不能直接訪問外部函數(shù)的arguments與this對象。
function f1() { console.log(arguments.length); f2=function() { console.log(arguments.length); } return f2; } var f=f1(1,2,3); f();
運(yùn)行結(jié)果:
3
0
3.2、構(gòu)造函數(shù)
在javascript中對象構(gòu)造函數(shù)可以創(chuàng)建一個對象。
<script type="text/javascript"> /*構(gòu)造函數(shù)*/ //可以簡單的認(rèn)為是一個類型的定義 function Student(name,age){ this.name=name; this.age=age; this.show=function(){ console.log(this.name+","+this.age); } } //通過new關(guān)鍵字調(diào)用構(gòu)造函數(shù),創(chuàng)建一個對象tom var rose=new Student("rose",18); var jack=new Student("jack",20); rose.show(); jack.show(); </script>
3.3、函數(shù)調(diào)用
3.3.1、call
調(diào)用一個對象的一個方法,以另一個對象替換當(dāng)前對象
call([thisObj[,args])
hisObj 可選項。將被用作當(dāng)前對象的對象。args 將被傳遞方法參數(shù)序列。
call 方法可以用來代替另一個對象調(diào)用一個方法。call 方法可將一個函數(shù)的對象上下文從初始的上下文改變?yōu)橛?thisObj 指定的新對象。
示例:
/*構(gòu)造函數(shù)*/ function Student(name,age){ this.name=name; this.age=age; } show=function(add){ console.log(add+":"+this.name+","+this.age); } //通過new關(guān)鍵字調(diào)用構(gòu)造函數(shù),創(chuàng)建一個對象tom var rose=new Student("rose",18); var jack=new Student("jack",20); //調(diào)用show方法,指定上下文,指定調(diào)用對象,this指向rose,“大家好是參數(shù)” show.call(rose,"大家好"); show.call(jack,"Hello");
運(yùn)行結(jié)果:
call方法中的參數(shù)都可以省去,第1個參數(shù)表示在哪個對象上調(diào)用該方法,或this指向誰,如果不指定則會指向window對象。
示例:
var name="無名"; var age=18; show.call();
結(jié)果:
undefined:無名,18
3.3.2、apply
apply([thisObj[,argArray]])
應(yīng)用某一對象的一個方法,用另一個對象替換當(dāng)前對象,與call類似。
如果 argArray 不是一個有效的數(shù)組或者不是arguments對象,那么將導(dǎo)致一個 TypeError。
如果沒有提供 argArray 和 thisObj 任何一個參數(shù),那么 Global 對象將被用作 thisObj, 并且無法被傳遞任何參數(shù)。
對于第一個參數(shù)意義都一樣,但對第二個參數(shù):
apply傳入的是一個參數(shù)數(shù)組,也就是將多個參數(shù)組合成為一個數(shù)組傳入,而call則作為call的參數(shù)傳入(從第二個參數(shù)開始)。
如 func.call(func1,var1,var2,var3)對應(yīng)的apply寫法為:func.apply(func1,[var1,var2,var3])
同時使用apply的好處是可以直接將當(dāng)前函數(shù)的arguments對象作為apply的第二個參數(shù)傳入
示例代碼:
/*構(gòu)造函數(shù)*/ function Student(name,age){ this.name=name; this.age=age; } show=function(greeting,height){ console.log(greeting+":"+this.name+","+this.age+","+height); } //通過new關(guān)鍵字調(diào)用構(gòu)造函數(shù),創(chuàng)建一個對象tom var rose=new Student("rose",18); var jack=new Student("jack",20); //調(diào)用show方法,指定上下文,指定調(diào)用對象,this指向rose,“大家好是參數(shù)” show.apply(rose,["大家好","178cm"]); show.apply(jack,["Hello","188cm"]);
運(yùn)行結(jié)果:
從上面的示例中可以發(fā)現(xiàn)apply的第2個參數(shù)是一個數(shù)組,數(shù)組中的內(nèi)容將映射到被調(diào)用方法的參數(shù)中,如果單這樣看發(fā)現(xiàn)不如call方便,其實如果直接取方法的參數(shù)arguments則apply要方便一些。通過簡單的變化就可以替代call。
function display(){ show.apply(jack,arguments); } display("hi","224cm");
結(jié)果:
hi:jack,20,224cm
javascript里call和apply操作符可以隨意改變this指向
如果在javascript語言里沒有通過new(包括對象字面量定義)、call和apply改變函數(shù)的this指針,函數(shù)的this指針都是指向window的。
關(guān)于this指針,我的總結(jié)是:是誰調(diào)用的函數(shù),那么這個函數(shù)中的this指針就是它;如果沒有明確看出是誰調(diào)用的,那么應(yīng)該就是window調(diào)用的,那么this指針就是window。
3.3.3、caller
在一個函數(shù)調(diào)用另一個函數(shù)時,被調(diào)用函數(shù)會自動生成一個caller屬性,指向調(diào)用它的函數(shù)對象。如果該函數(shù)當(dāng)前未被調(diào)用,或并非被其他函數(shù)調(diào)用,則caller為null。
在JavaScript的早期版本中,F(xiàn)unction對象的caller屬性是對調(diào)用當(dāng)前函數(shù)的函數(shù)的引用
function add() { console.log("add被調(diào)用"); //add方法的調(diào)用函數(shù),如果調(diào)用add方法的不是函數(shù)則為null console.log(add.caller); } function calc(){ add(); } //直接調(diào)用add方法 add(); //間接通過calc方法調(diào)用 calc();
運(yùn)行結(jié)果:
caller與this還是有區(qū)別的,this是指調(diào)用方法的對象,而caller是指調(diào)用函數(shù)的函數(shù)。
<script type="text/javascript"> function add(n) { console.log("add被調(diào)用"); if(n<=2){ return 1; } return add.caller(n-1)+add.caller(n-2); } function calc(n){ console.log("calc被調(diào)用"); return add(n); } //1 1 2 console.log(calc(3)); </script>
結(jié)果:
3.3.4、Callee
當(dāng)函數(shù)被調(diào)用時,它的arguments.callee對象就會指向自身,也就是一個對自己的引用
function add(n1,n2){ console.log(n1+n2); //arguments.callee(n1,n2); //指向add方法 return arguments.callee; } add(1,2)(3,4)(5,6)(7,8)(8,9);
運(yùn)行結(jié)果:
當(dāng)?shù)?次調(diào)用add方法時輸入3,立即將函數(shù)返回再次調(diào)用,每次調(diào)用后又返回自己,這樣可以實現(xiàn)鏈?zhǔn)骄幊獭?/p>
3.5、立即執(zhí)行函數(shù)表達(dá)式 (IIFE)
IIFE即Immediately-Invoked Function Expression,立即執(zhí)行函數(shù)表達(dá)式
3.5.1、匿名函數(shù)與匿名對象
匿名函數(shù)就是沒有名稱的函數(shù),javascript中經(jīng)常會使用匿名函數(shù)實現(xiàn)事件綁定,回調(diào),實現(xiàn)函數(shù)級的私有作用域,如下所示:
function(){ console.log("這是一個匿名函數(shù)"); };
匿名對象:
{ name:"foo", show:function(){ console.log(this.name); } }
沒有名稱的匿名函數(shù)也叫函數(shù)表達(dá)式,它們間是有區(qū)別的。
3.5.2、函數(shù)與函數(shù)表達(dá)式
下面是關(guān)于函數(shù)與函數(shù)表達(dá)式定義時的區(qū)別
a)、函數(shù)定義(Function Declaration)
function Identifier ( Parameters ){ FunctionBody }
function 函數(shù)名稱(參數(shù)){函數(shù)主體}
在函數(shù)定義中,參數(shù)(Parameters)標(biāo)識符(Identifier )是必不可少的。如果遺漏,會報提示錯誤:
代碼:
function(){ console.log("這是一個匿名函數(shù)"); };
結(jié)果:
b)、函數(shù)表達(dá)式(Function Expression)
function Identifier(Parameters){ FunctionBody }
函數(shù)表達(dá)式中,參數(shù)和標(biāo)識符都是可選的,與函數(shù)定義的區(qū)別是標(biāo)識符可省去。
其實,"function Identifier(Parameters){ FunctionBody }"并不是一個完整的函數(shù)表達(dá)式,完整的函數(shù)的表達(dá)式,需要一個賦值操作。
比如: var name=function Identifier(Parameters){ FunctionBody }
3.5.3、立即執(zhí)行函數(shù)表達(dá)式與匿名對象
//1 正常定義函數(shù) function f1(){ console.log("正常定義f1函數(shù)"); }; //2 被誤解的函數(shù)表達(dá)式 function(){ console.log("報錯Unexpected token ("); }(); //3 IIFE,括號中的內(nèi)容被解釋成函數(shù)表達(dá)式 (function(){ console.log("IIFE,正常執(zhí)行"); })(); //4 函數(shù)表達(dá)式 var f2=function(){ console.log("這也被視為函數(shù)表達(dá)式"); };
第3種寫法為什么這樣就能立即執(zhí)行并且不報錯呢?因為在javascript里,括號內(nèi)部不能包含語句,當(dāng)解析器對代碼進(jìn)行解釋的時候,先碰到了(),然后碰到function關(guān)鍵字就會自動將()里面的代碼識別為函數(shù)表達(dá)式而不是函數(shù)聲明。
如果需要將函數(shù)表達(dá)式或匿名對象立即執(zhí)行,可以使用如下方法:
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>IIFE</title> </head> <body> <script type="text/javascript"> //調(diào)用匿名函數(shù) (function() { console.log("這是一個函數(shù)表達(dá)式"); })(); //調(diào)用匿名對象 ({ name: "foo", show: function() { console.log(this.name); } }).show(); console.log({ a: 1 }.a); console.log({ a: function() {} }.a()); </script> </body> </html>
運(yùn)行結(jié)果:
3.5.4、各種IIFE的寫法
//最常用的兩種寫法 (function(){ /* code */ }()); // 老師推薦寫法 (function(){ /* code */ })(); // 當(dāng)然這種也可以 // 括號和JS的一些操作符(如 = && || ,等)可以在函數(shù)表達(dá)式和函數(shù)聲明上消除歧義 // 如下代碼中,解析器已經(jīng)知道一個是表達(dá)式了,于是也會把另一個默認(rèn)為表達(dá)式 // 但是兩者交換則會報錯 var i = function(){ return 10; }(); true && function(){ /* code */ }(); 0, function(){ /* code */ }(); // 如果你不怕代碼晦澀難讀,也可以選擇一元運(yùn)算符 !function(){ /* code */ }(); ~function(){ /* code */ }(); -function(){ /* code */ }(); +function(){ /* code */ }(); // 你也可以這樣 new function(){ /* code */ } new function(){ /* code */ }() // 帶參
如果是函數(shù)表達(dá)式,可直接在其后加"()"立即執(zhí)行。
如果是函數(shù)聲明,可以通過"()"、"+"、"-"、"void"、"new"等運(yùn)算符將其轉(zhuǎn)換為函數(shù)表達(dá)式,然后再加"()"立即執(zhí)行。
3.5.5、參數(shù)
函數(shù)表達(dá)式也是函數(shù)的一種表達(dá)形式,同樣可以像函數(shù)一樣使用參數(shù),如下所示:
(function (n){ console.log(n); })(100);
輸出:100
其實通過IIFE還能形成一個類似的塊級作用域,當(dāng)塊內(nèi)的程序在使用外部對象時將優(yōu)先查找塊內(nèi)的對象,再查找塊外的對象,依次向上。
(function(win,undfd){ win.console.log("Hello"==undfd); })(window,undefined);
3.5.6、添加分號
為了避免與其它的javascript代碼產(chǎn)生影響后報錯,常常會在IIFE前增加一個分號,表示前面所有的語句都結(jié)束了,開始新的一語句。
var k=100 (function (n){ console.log(n); })(k);
上面的腳本會報錯,因為javascript解釋器會認(rèn)為100是函數(shù)名。
var k=100 ;(function (n){ console.log(n); })(k);
這樣就正確了,在javascript中一行語句的結(jié)束可以使用分號,也可以不使用分號,因為一般的自定義插件會使用IIFE,這是一段獨(dú)立的代碼,在應(yīng)用過程中不能保證用戶會加上分號,所以建議在IIFE前加上分號。
3.5.7、IIFE的作用
1)、提高性能
減少作用域查找時間。使用IIFE的一個微小的性能優(yōu)勢是通過匿名函數(shù)的參數(shù)傳遞常用全局對象window、document、jQuery,在作用域內(nèi)引用這些全局對象。JavaScript解釋器首先在作用域內(nèi)查找屬性,然后一直沿著鏈向上查找,直到全局范圍。將全局對象放在IIFE作用域內(nèi)提升js解釋器的查找速度和性能。
function(window, document, $) {
}(window, document, window.jQuery);
2)、壓縮空間
通過參數(shù)傳遞全局對象,壓縮時可以將這些全局對象匿名為一個更加精簡的變量名
function(w, d, $) { }(window, document, window.jQuery);
3)、避免沖突
匿名函數(shù)內(nèi)部可以形成一個塊級的私有作用域。
4)、依賴加載
可以靈活的加載第三方插件,當(dāng)然使用模塊化加載更好(AMD,CMD),示例如下。
A.html與B.html文件同時引用公用的common.js文件,但是只有A.html需要使用到StuObj對象,B.html不需要,但使用其它方法。
Student.js
var StuObj = { getStu: function(name) { return new Student(name); } } /*構(gòu)造函數(shù)*/ function Student(name) { this.name = name; this.show = function() { console.log("Hello," + this.name); } }
Common.js
function other1() {} function other2() {} (function($) { if($) { $.getStu("Tom").show(); } })(typeof StuObj=="undefined"?false:StuObj);
A.HTML
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>A</title> </head> <body> <script src="js/Student.js" type="text/javascript" charset="utf-8"></script> <script src="js/common.js" type="text/javascript" charset="utf-8"></script> </body> </html>
B.HTML
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title></title> </head> <body> <script src="js/common.js" type="text/javascript" charset="utf-8"></script> <script type="text/javascript"> other1(); </script> </body> </html>
3.5.8、IIFE的變形
也許有人會說IIFE將參數(shù)放在最后,需要移動到文檔的末尾才能看到參數(shù),比較麻煩,那么可以將IIFE變形為如下形式:
(function(n){ console.log(n); //認(rèn)為這里有30000代碼 }(100));
如果中間有很長的代碼,參數(shù)100只有到文檔的末尾才可以看得到,變形后的結(jié)果:
(function(exp){ exp(100); }(function(n){ console.log(n); //認(rèn)為這里有30000代碼 }));
修改后的代碼中有兩個函數(shù)表達(dá)式,一個作為參數(shù),就是我們主要要完成的功能向控制臺輸出數(shù)字,另一個作來IIFE立即執(zhí)行的函數(shù),主要的功能函數(shù)變成的IIFE的參數(shù)了。
(function(win, doc, $) { }(window, document, jQuery)); ( function(library) { library(window, document, window.jQuery); } (function(window, document, $) { }) );
bootstrap的寫法:
+function(yourcode) { yourcode(window.jQuery, window, document); }(function($, window, document) { $(function() {}); //jQueryDOM加載完成事件 });
結(jié)合call或apply的寫法:
(function(x){console.log(x)}).call(window,888); (function(x){console.log(x)}).apply(window,[999]);
輸出:888 999
四、示例下載
http://xiazai.jb51.net/201612/yuanma/javascript003-master_jb51.rar
以上就是本文的全部內(nèi)容,希望本文的內(nèi)容對大家的學(xué)習(xí)或者工作能帶來一定的幫助,同時也希望多多支持腳本之家!
相關(guān)文章
微信小程序使用map組件實現(xiàn)檢索(定位位置)周邊的POI功能示例
這篇文章主要介紹了微信小程序使用map組件實現(xiàn)檢索(定位位置)周邊的POI功能,涉及微信小程序基于map組件與高德地圖PAI接口的定位操作相關(guān)使用技巧,需要的朋友可以參考下2019-01-01JavaScript實現(xiàn)定時頁面跳轉(zhuǎn)功能示例
這篇文章主要介紹了JavaScript實現(xiàn)定時頁面跳轉(zhuǎn)功能,涉及javascript結(jié)合時間函數(shù)定時觸發(fā)自定義函數(shù)功能操作技巧,需要的朋友可以參考下2017-02-02