JS中function的一些淺見
它到底是什麼
String Array 都是系統內置對象(已經定義好,可以直接使用)當然,這貨也是一樣,我們之前定義的函數,其實就是一個這貨的實例。
在JS中,所有的對象都是由函數實現的,函數的數據類型是object。So,我們以前定義的函數也是一個對象。
幾種寫法
1 function fn1(a,b){ 2 return a+b; 3 } 4 5 //前面表示參數,後面表示函數語句 6 var fn2 = new Function("a","b","return a+b"); 7 8 // 匿名函數 9 var fn3=function(a,b){ 10 return a+b; 11 } 12 13 14 console.log(fn1(1,2)); 15 console.log(fn2(1,2)); 16 console.log(fn3(1,2)); // 註意,一定要在聲明函數的後面調用
另外,如果函數沒有明確的返回值,或者調用了沒有參數的return,那麼它真正返回的值是undefined
1 function fn(){ 2 //..... 3 } 4 5 6 function fn1(){ 7 return; 8 } 9 10 11 console.log(fn()===undefined); // true 12 console.log(fn1()===undefined); // true
arguments
arguments只有在代碼運行的時候才起作用,它是一個數組(準確的說是偽數組),保存函數的參數。
1 function fn(){ 2 var sum=0; 3 for(var i=0;i<arguments.length;i++){ 4 sum+=arguments[i]; 5 } 6 return sum; 7 } 8 9 var sum = fn(1,2); 10 var sum2 = fn(1,2,3); 11 console.log(sum); // 3 12 console.log(sum2); // 6 13 14 function fn1(a,b,c,d){ 15 console.log(arguments.length); 16 console.log(arguments[0]); 17 } 18 19 fn1(); // 0 、 undefined 20 fn1(1); // 1 、 1 21 fn1('a',2); // 2 、 a 22 fn1('李志',2,3); // 3 、 李志 23 fn1('李B',2,2,3,4,4); // 6 、 李B
Length
我們需要瞭解兩個東東,形參與實參(不同的資料書籍可能叫法有所差異)
形參:函數定義的時候的參數 實參:調用函數的時候傳遞的參數
length指的是形參個數 arguments.length指的是實參個數
1 function fn(a, b) { 2 console.log(fn.length); 3 console.log(arguments.length); 4 } 5 6 fn(1, 2); // 2 2 7 fn(1); // 2 1
call apply
1,借用另一個對象的方法 2,替換this指向
Apply方法 調用函數,並用指定對象替換函數的this值,同時用指定數組替換函數的參數。
Call方法 調用一個對象的方法,用另一個對象替換當前對象。
1 //對象1 2 var obj1={ 3 getAllStudentsNumbers:function(sum,sum1){ 4 return sum+sum1} 5 }; 6 7 //對象2 8 var obj2={ 9 getDetail:function(){ 10 return {name:'阿拉三',age:'18'} 11 } 12 }; 13 console.log(obj1.getAllStudentsNumbers.call(obj2,10,200)); // 210 14 console.log(obj1.getAllStudentsNumbers.apply(obj2,[10,200])); // 210
Function.apply(obj,args)方法能接收兩個參數
obj:這個對象將代替Function類里this對象
args:這個是數組,它將作為參數傳給Function(args-->arguments)
我們通過如下方式將其轉換成數組
1 /* slice : 截取數組,返回的還是數組,這裡我們截取全部 */ 2 var divs = document.getElementsByTagName("div") 3 var domNodes = Array.prototype.slice.call(divs);
還可以實現繼承,在上篇文章中說過,這裡不做贅述。
caller callee
caller屬性 獲取調用當前函數的函數。caller屬性只有當函數正在執行時才被定義。
返回函數調用者,主要用於察看函數本身被哪個函數調用.
1 function fn() { 2 //判斷某函數是否被調用 3 if (fn.caller) { 4 alert(fn.caller.toString()); 5 } else { 6 alert("函數直接執行"); 7 } 8 } 9 10 function fn1() { 11 fn(); 12 } 13 fn1(); 14 fn();
callee屬性 返回正被執行的 Function 對象,即指定的Function 對象的正文。
如下是一個遞歸演算法 - 計算 1+2+3+4+...+n
什麼是遞歸? 可以這樣理解,一個方法,自己調用自己,用上一次調用得出的結果作為這次的參數。
傳統方式的缺點:
1、破壞了,零重覆法則,當一旦函數名稱更改,需要更改多處
2、fn是一個全局變數,fn內部一般使用局部變數,而這裡是一個全局變數,這是一個潛在的全局變數污染
1 var fn=function(n){ 2 return n>0 ? n+fn(n-1) : 0; 3 } 4 console.log('採用傳統方式:'+fn(10));
優點:這樣就讓代碼更加簡練。又防止了全局變數的污染
1 var fn=(function(n){ 2 return n>0 ? n+arguments.callee(n-1) : 0; 3 })(10); 4 console.log('採用callee方式: '+fn);
constructor prototype
constructor屬性,就是用來構造對象實例的函數引用。
prototype屬性,獲取對象的原型。
每一個構造函數都有一個prototype屬性,指向另一個對象。這個對象的所有屬性和方法,都會被構造函數的實例繼承。這意味著,我們可以把那些不變的屬性和方法,直接定義在prototype對象上。
contructor,prototype屬性是系統自動生成的。但本質上只是是函數對象的屬性而已。
對象是一個函數,而函數對象含有contructor,prototype等屬性,
那麼實例化的過程就是拷貝構造函數屬性的過程,所以每個實例自然就擁有了contructor,prototype這兩個屬性。
自定義對象:函數實現的--函數又是Function的一個實例,所以這個自定義對象含有Function對象的一切屬性和方法
1 var product = function(){} 2 /*自動有一個 prototype屬性 它是一個對象--- 原型對象*/ 3 /* product.prototype也是對象,對象都是函數實現的,這貨也包含Function對象的一切屬性和方法,所以他也有。*/ 4 product.prototype.buy=function(){} 5 product.prototype={}
bind toString
Bind方法,創建具有與原始函數相同的主體的綁定函數。 在綁定功能中,this對象解析為傳入的對象。 該綁定函數具有指定的初始參數。
關於Function.prototype.bind(),我們下次專門去討論這個它。
好消息是,IE8以下並不支持。
toString 返回對象的字元串表示形式。