JS 學習筆記--8---Function類型

練習使用的瀏覽器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 */
View Code
相關文章
相關標籤/搜索