練習使用的瀏覽器IE11 javascript
JS 中Function類型其實是一種對象,每個函數實際上都是Function類型的一個實例,每個函數都有一些默認的屬性和方法。因爲函數是對象,故函數名實際上也是一個指向函數對象的指針變量 java
一、聲明一個函數 數組
直接用關鍵字function來聲明函數,JS是弱類型的語言,聲明的時候參數個數不限,只是須要寫參數名,不須要寫參數的關鍵字var,不須要指定返回值以及類型,若是有返回值直接在函數後面一個return value 便可。 瀏覽器
方法一:function func(num1,num2){return 1;}//num1,num2是參數名,返回值爲1 app
方法二:利用變量來聲明函數,var box=function(num1,num2){};至關於給window對象的自定義屬性box註冊方法 ide
方法三:利用析構函數來聲明,可是最好不要用這種方式來聲明,由於這種方式瀏覽器會解析兩次,效率不高,第一次是解析整個ECMAScript表達式,第二次是解析析構函數中傳遞的字符串列表,var box=new Function('num1','num2','return num1+num2');注意析構函數裏面的參數以及語句是帶有引號的。這種方式可以更好的理解 Function是一個對象的,函數名是一個指針的概念 函數
二、調用函數 this
方法一中聲明的函數直接寫函數名就能夠調用[fun(10,20)],spa
方法二和方法三聲明的函數調用時用變量名後面加括號裏面寫上要傳遞的參數值[box(10,20)]; prototype
函數的返回值能夠直接賦值給一個變量[var box=func(20,10);],也能夠當作實參直接傳遞給另外的函數[alert(func(10,20));]
ECMAScript 中的函數名自己就是變量,因此函數也能夠做爲值來使用。也就是說,不只能夠像傳遞參數同樣把一個函數傳遞給另外一個函數, 並且能夠將一個函數做爲另外一個函數的結果返回
//將一個函數做爲結果返回 其實就至關於執行這個函數,而後把這個函數的返回值給返回 function sum(num1,num2){ return num1+num2; } function func(num1){ return sum(num1,10); } alert(func(10));//20 //其實函數名,也就是一個對象的變量,執行的是函數的地址,至關於一個指針 //將函數名當作一個參數傳遞給另一個函數, function sumFunc(num1,num2){ return num1+num2; } function func(sum,num1){ return sum(num1,10); } alert(func(sumFunc,10));//20
JS 中沒有函數重載的說法,函數調用的時候,會以就近原則來調用
JS 中調用函數的時候容許調用者和被調用這的參數個數不同,也不會報錯,可是若是參數個數不夠的話,在執行時由於有的參數沒有賦值可能會報錯,參數時從前向後對應傳遞接收的
三、函數的內部屬性 arguments
arguments 是一個類數組,用來保存函數傳遞過來的參數,數組類型
在聲明函數的時候,有的時候咱們並不知道調用者到底要傳遞多少個參數過來,好比說,求一串數的累加和,若是調用者不是用數組傳遞過來而是用直接傳遞給函數的方式傳遞[func(10,20...)],那麼在聲明函數實體的時候就不知道要聲明多少個參數,這時能夠不寫參數名,在函數內部用arguments來代替,arguments是一個類數組,保存的是擁有這個對象的函數的參數的值,用索引的方法既能夠獲取對應的參數的值,使用以下:
function func(){ var res=0; for(var i=0;i<arguments.length;i++){ res+=arguments[i]+" | "; } return res; } alert(func(20,30,40));
arguments 中還有一個很重要的屬性就是callee,是一個指針變量,指向的是擁有這個arguments類數組的函數,其實也就是arguments所在的函數自己,在遞歸的時候最好用這個屬性,由於若是函數名改變了,也不須要改變內部的實現,arguments.callee()始終表明的是這個函數自己
//用arguments.callee的好處是,當函數名改變了之後,不須要改動遞歸出的函數, function box(num){ if(num<=1){ return 1; }else{ return num*arguments.callee(num-1); //arguments.callee表明的是函數的自己,故和上面是一樣的效果 } } alert(box(3));//6
四、函數的內部屬性 this
this 這個屬性表明的是它所在的對象自己,和C#中this表明實體對象自己是同樣的,this 引用的是函數以執行操做的對象,或者說函數調用語句所處的那個做用域
window是JS中最大的一個對象,在window對象中聲明一個變量其實就是給window這個對象聲明一個屬性,var box=1;至關於 window.box=1;也就等價於this.box=1;
當在全局做用域中調用函數時,this 對象引用的就是 window。
在顯示的聲明一個對象box,這個box中使用的this就表明的是box自己,this.color就是返回的box中屬性color的值,而不是window對象中color的值
// this 表明的是坐在的對象自己,下面在對象box中的this,就表明對象box var color='紅色'; // window對象的屬性, var box={ color:'藍色', run:function(){ alert(this.color);//藍色 return this.color; } } alert(window.color);//紅色 alert(this.color); //紅色 此處this表明的是window對象,故this.color是表明的window的屬性 alert(box.run()); //藍色 window.co='hh'; //和上面的color是等價的,都屬於window對象的屬性 alert(this.co);
五、函數的屬性 length
函數的屬性length表明的是函數但願接收的參數的個數,是由聲明函數時參數列表中的個數決定的
六、函數的屬性 prototype
prototype 是保存全部實例方法的真正所在,也就是原型。
prototype 下面有兩個方法 apply(),call(),這兩個方法都是函數非繼承而來的方法, 是每個函數都具備的方法。這兩個方法的用途都是在特定的做用域中調用函數,也就是說調用特定的對象下面調用函數,(固然這個對象不必定已經聲明有這個方法),實際上也就是等價於設置函數內部this對象的值,有點相似於C#的反射中調用對象的方法。
func.apply():這個方法有兩個參數,第一個是要執行這個方法的做用域,也就是傳遞一個對象過去,第二個參數是一個數組,這個數組中是存放的調用的函數func的實參,也就是要傳遞給func的值,固然第二個參數能夠省略。func.apply(this, [num1, num2]);。若是是在一個函數中調用能夠用arguments把這個函數的參數傳遞過去,前提是這個類數組中有參數。可是最好是保證這個類數組中存放的是你想要傳遞給func函數的實參的值。雖然個數不匹配也不會出錯,可是業務上可能不對
func.call():這個方法和上面的apply()方法是同樣的,不一樣的是參數,第一個一樣是做用域,是同樣的,其他的參數是直接傳遞給函數的,而不是傳遞一個數組過去。就是說傳遞的參數順序和方式是按照正常調用函數的形式和方法。func.call(this, num1, num2);
這兩個方法最主要的功能是是可以擴展函數賴以運行的做用域,也就是改變函數運行所在的做用域
使用這apply()和call()這兩個方法來擴充做用域最大的好處是對象不須要與方法發生任何的耦合關係,也就是上面說的對象中可能不存在這個方法,但只要存在這個對象就OK。【耦合:關聯的意思,修改和維護會發生連鎖反應】。也就是說 box 對象和sayColor()方法之間不會有多餘的關聯操做,好比 box.sayColor = sayColor;[ box對象中無需顯示寫上這條語句,也能夠經過sayColor.call(box,'red')或者apply來調用方法sayColor,而且調用時sayColor方法的做用域是在對象box內部 ].
//call()和apply()方法最主要的是用於擴展函數依賴的做用域 var color='red'; var box={ color:'green' } function sayColor(){ return this.color; } alert(sayColor()); //red 對象是window alert(sayColor.call(this)); //red 對象是window alert(sayColor.apply(this)); //red 對象是window alert(sayColor.call(window)); //red 對象是window alert(sayColor.apply(window)); //red 對象是window alert(sayColor.call(box)); //green 對象是box alert(sayColor.apply(box)); //green 對象是box
練習的代碼:以IE10爲主
1 /* 函數的聲明 2 3 //聲明一個函數,沒有參數和返回值 4 function func(){ 5 alert('diao yong di shi hou zhi xin'); 6 } 7 func(); 8 9 //聲明一個函數,帶有兩個參數,因爲JS是弱類型的語言,故函數的參數時不須要使用var的 10 function func(num1,num2){ 11 alert(num1+num2); 12 } 13 func(10,20); 14 15 //聲明一個函數,帶有兩個參數和返回值,JS中返回值直接用return便可,函數名前不須要標註帶有返回值 16 function func(num1,num2){ 17 return num1+num2; 18 } 19 alert(func(10,20));//30 20 21 //能夠把函數的返回值直接賦值給一個變量,而後直接操做變量 22 function func(num1,num2){ 23 return num1+num2; 24 } 25 var a=func(10,20); 26 alert(a); //11 27 28 //return還有一個功能就是,結束函數的執行 29 function func(num1,num2){ 30 if(num1>10){ 31 return 11; 32 } 33 return num1+num2; 34 } 35 alert(func(13,20)); //11 36 37 // JS 調用的時候傳遞的參數個數和函數原型中參數個數能夠不同 38 function func(num1,num2){ 39 return num1+num2; 40 } 41 42 alert(func(20,'ahc',9)); 43 44 //ECMAScript 函數不介意傳遞進來多少參數,也不會由於參數不統一而錯誤。實際上, 45 函數體內能夠經過 arguments 對象來接收傳遞進來的參數,arguments 能夠用數組來取值 46 function func(){ 47 var res=0; 48 for(var i=0;i<arguments.length;i++){ 49 res+=arguments[i]+" | "; 50 } 51 return res; 52 } 53 54 alert(func(20,30,40)); 55 56 // JS 中沒有函數重載的說法,函數和變量等的調用都是就近原則 57 function func(num1,num2){ 58 return num1+num2; 59 } 60 function func(num1){ 61 return num1; 62 } 63 alert(20,30);//20 執行的第二個函數,就近原則 64 65 //將一個函數的返回結果值做爲另一個函數的參數進行傳遞 66 function sum(num1,num2){ 67 return num1+num2; 68 } 69 70 function func(num1){ 71 return num1+10; 72 } 73 alert(sum(func(10),10));//30 74 75 //用變量初始化的方式聲明一個函數,而後用變量名加參數列表來調用這個函數 76 //這種聲明方法,就是給變量名註冊一個事件的形式 77 var box=function(num1,num2){ 78 return num1+num2; 79 } 80 alert(box(10,10));//20 81 82 //使用析構函數來聲明一個函數,可是這種方法效率低,由於會解析兩次 83 //第一次解析整個表達式(ECMAScript常規代碼),第二次就是解析傳入構造函數中的字符串 84 //用這種方式可以更好的理解函數是對象,函數名是一個指針的概念 85 var box=new Function('num1','num2','return num1+num2'); 86 alert(box(10,10));20 87 88 */ 89 90 /* 91 //將一個函數做爲結果返回 其實就至關於執行這個函數,而後把這個函數的返回值給返回 92 function sum(num1,num2){ 93 return num1+num2; 94 } 95 function func(num1){ 96 return sum(num1,10); 97 } 98 alert(func(10));//20 99 100 //Function類型其實也是一個對象,既然是對象,那也就具備和其餘對象同樣的屬性方法等, 101 //其實函數名,也就是一個對象的變量,執行的是函數的地址,至關於一個指針 102 //將函數名當作一個參數傳遞給另一個函數, 103 function sumFunc(num1,num2){ 104 return num1+num2; 105 } 106 function func(sum,num1){ 107 return sum(num1,10); 108 } 109 alert(func(sumFunc,10));//20 110 111 */ 112 113 /* 函數的內部屬性 arguments 和 this 114 //函數的遞歸 115 function box(num){ 116 if(num<=1){ 117 return 1; 118 }else{ 119 return num*box(num-1);//本身調用本身 120 } 121 } 122 alert(box(3));//6 123 124 //arguments 是一個類數組,用來保存函數傳遞過來的參數,數組類型 125 //arguments.callee 是一arguments的一個屬性,是一個指針變量, 126 //指向的是擁有這個argumens屬性的函數,也就是說表明了他所在的這個函數自己 127 //用arguments.callee的好處是,當函數名改變了之後,不須要改動遞歸出的函數, 128 function box(num){ 129 if(num<=1){ 130 return 1; 131 }else{ 132 return num*arguments.callee(num-1); 133 //arguments.callee表明的是函數的自己,故和上面是一樣的效果 134 } 135 } 136 alert(box(3));//6 137 138 // this 對象表明的是對象的自己 139 // 和 C# 中的this差很少,C# 中的this表明的也是實例化的對象的自己 140 //默認狀況下 this 帶表的是window對象,window是JS中最大的一個對象 141 //從下面能夠看出 在window對象下 this就等於window 142 alert(window); //object Window 143 alert(typeof window); //object 144 alert(this); //object Window 145 alert(typeof this); //onject 146 147 var color='hong se'; // color 是window的一個屬性 148 alert(window.color); //hong se 輸出window的屬性 149 alert(this.color); //hong se 和上面結果相等,說明this在此處表明的是window對象的自己 150 151 // this 表明的是坐在的對象自己,下面在對象box中的this,就表明對象box 152 var color='紅色'; // window對象的屬性, 153 154 var box={ 155 color:'藍色', 156 run:function(){ 157 alert(this.color);//藍色 158 return this.color; 159 } 160 } 161 alert(window.color);//紅色 162 alert(this.color); //紅色 此處this表明的是window對象,故this.color是表明的window的屬性 163 alert(box.run()); //藍色 164 165 window.co='hh'; //和上面的color是等價的,都屬於window對象的屬性 166 alert(this.co); 167 168 // 下面是經過給對象添加方法來改變this的做用域 169 window.color='紅色'; //等價於 var color='紅色' 170 171 var box={ 172 color:'藍色' 173 }; 174 175 function sayColor(){ 176 alert(this.color); 177 } 178 179 sayColor(); // 紅色 180 box.sayColor=sayColor; //給對象添加一個方法, 181 //上面這句話改變了 sayColor 的做用域在box對象裏面,故這個方法裏面的this也就是指的box對象 182 box.sayColor(); // 藍色 183 184 */ 185 186 /* 函數的屬性和方法 length,prototype[原型,標準] 187 188 // 函數中的length屬性返回的是函數的參數的個數 189 function box(nm1,num2){}; 190 alert(box.length); // 2 191 function func(num1,num2,num3,num4){}; 192 alert(func.length); // 4 193 // prototype 屬性是保存實例方法的真正所在的位置,也就是保存的原型 194 //包含兩個非繼承而來的方法 apply()和call()方法,都是用在特定的做用域中調用, 195 //至關於改變函數的this,也就是說改變函數所處的對象,有點像C#中的反射調用對象方法 196 197 // box.apply()方法,兩個參數,第一個參數是要操做的對象,第二個參數是方法的參數數組 198 function sum(num1,num2){ 199 return num1+num2; 200 } 201 202 function saySum1(num1,num2){ 203 //第一個參數時表明的是要調用的是哪個對象的sum方法,後面是這個方法的參數列表,注意傳遞的是一個數組 204 return sum.apply(this,[num1,num2]);//this至關於window 205 } 206 function saySum2(num1,num2){ 207 return sum.apply(this,arguments); 208 //arguments 表明的是當前函數[saySum2]的參數列表,是一個類函數,直接傳遞給函數sum 209 } 210 alert(saySum1(10,20)); //30 211 alert(saySum2(10,20)); //30 212 213 //第一個參數的不一樣,函數的做用域是不同的 214 function sum(num1,num2){ 215 return num1+num2; 216 } 217 218 function saySum1(num1,num2){ 219 return sum.apply(this,arguments);//是在window對象中執行的 220 } 221 function saySum2(num1,num2){ 222 return sum.apply(box,arguments);//是執行在box對象中的方法 223 } 224 var box ={ 225 num1:'acd', 226 num2:'ddd', 227 } 228 alert(saySum1(10,20)); //30 229 alert(saySum2(10,10)); //20 230 231 //方法 call()和上面的apply()方法是同樣的,僅僅在於接收參數的方式不一樣 232 //call()第一個參數一樣是傳遞做用域對象,其他的參數是直接傳給函數的,而不是傳遞一個數組 233 234 function sum(num1,num2){ 235 return num1+num2; 236 } 237 238 function saySum1(num1,num2){ 239 return sum.call(this,num1,num2) 240 } 241 242 function saySum2(num1,num2){ 243 return sum.call(box,num1,num2); 244 } 245 var box={}; 246 247 alert(saySum1(10,20));//30 248 alert(saySum2(20,20));//40 249 250 //call()和apply()方法最主要的是用於擴展函數依賴的做用域 251 252 var color='red'; 253 var box={ 254 color:'green' 255 } 256 257 function sayColor(){ 258 return this.color; 259 } 260 261 alert(sayColor()); //red 對象是window 262 alert(sayColor.call(this)); //red 對象是window 263 alert(sayColor.apply(this)); //red 對象是window 264 alert(sayColor.call(window)); //red 對象是window 265 alert(sayColor.apply(window)); //red 對象是window 266 alert(sayColor.call(box)); //green 對象是box 267 alert(sayColor.apply(box)); //green 對象是box 268 */