廢話篇:
今天看到了Function的內容,各種暈,各種混淆有木有。簡直是挑戰個人腦經急轉彎的極限啊。不過,最終這一難題還是被我攻克了,哇咔咔。現在就把這東西記下來,免得到時候又忘了就悲催了。。。。
正文篇:
function的定義方法,及function對象的理解。
在我大js中秉承着一切都是對象的原則,不論是方法還是其他都不例外。
我們在使用java的時候經常要編寫方法,這時候其用的關鍵字是function,而在js中我們在編寫函數的時候也是用這個關鍵字,所以常常會使我們錯把兩者進行關聯,所以常常會吧我們引導只一個錯誤的方向。
所以接下來我們先從function的定義開始說起。
一:實際上就和我們最為平常的方法是一樣的。
function fname(test){ alert(""+test); }
二:通過Function的函數的構造器進行函數對象的定義。
var fname = new Function("test", "alert(''+test);"); 第一個參數實際上是表示要傳入函數中的參數,二第二個參數表示的是當前的函數要執行的過程。兩個參數實際上都是string類型的。但是又上可以看出實際上當前的內容是十分的繁雜。
三:通過變量只帶一塊function關鍵字定義的方法來進行定義。
var fname = function(test){alert(""+test);}
上面的三種方法雖然最后都是聲明定義了一個函數,但是也是有區別的。第一種方法實際上是為函數命名為fname,而二三種方法使用起來實際上是把一個匿名函數賦值給一個變量。使用第二種方法來定義函數的時候,實際上就是調用構造函數並在每次解析的時候都會重新讀取並創建一新的函數對象,由此可見當在循環體中調用這樣的函數的時候會是十分的低效的,還有一點就是,當我們使用其創建一個函數對象的時候,其並不遵循典型的作用域,而是一直作為頂級函數來執行的。意思就是,當在函數內部調用它的時候,其實他並不會用函數內部定義的變量。而是只能使用全局變量。
第一三種方法實際上市定義了一種函數直接量也可以稱之為是一種函數表達式。當我們不為函數直接量定義名稱的時候。函數直接量就叫做匿名函數。那么我們如何調用一個匿名直接量,如下:
1、執行后得到返回值的函數調用
//方式一,調用函數,得到返回值。強制運算符使函數調用執行
(function(x,y){
alert(x+y);
return x+y;
}(3,4));
//方式二,調用函數,得到返回值。強制函數直接量執行再返回一個引用,引用在去調用執行
(function(x,y){
alert(x+y);
return x+y;
})(3,4);
//還有一種很奇葩的方式三 ~function(x,y){ ...//內容就不寫了啊,自行想象。 }(3,4); 這樣寫實際上也是可以執行的~可以吧函數表達式進行運算符操作並使用后面的小括號中傳入的參數。
2、執行后忽略返回值
//方式四,調用函數,忽略返回值
void function(x) {
x = x-1;
alert(x);
}(9);//這里實際上就是使用了void運算符,其用於計算之后的表達式並且不返回任何值。
嗯,最后看看錯誤的調用方式
//錯誤的調用方式
function(x,y){
alert(x+y);
return x+y;
}(3,4);//這種方式是沒有運算的。可以這樣認為,把匿名函數作為表達式的看的話,我們並沒有在一個計算的表達式中來調用函數表達式,所以其僅僅只是返回了表達式本身,而其本身就是一個函數不變量。
有點扯遠了。實際上在使用第一和第三種的方法來說的話,在第一次解析的時候會通過new Function來定義一個函數的對象,並把這一對象作為內部對象來進行存儲和運行。由此可知在js中每寫一個函數,實際上就是在其中存儲一個相關的函數對象,並在我們需要調用的時候對其進行調用。
接下來我們來具體的了解一下Function對象的定義和內容吧。
1.首先是我們最為常用的內容arguments對象。他的定義是,一個類似於數組的對象,對應的是傳遞給函數對象的屬性。arguments對象是一個所有的函數內部都可以用的函數內部變量。當我們調用函數的時候,他會存儲我們傳輸進來的參數的數據的。如下端的嗎。
1 function test(){ 2 if(arguments[0]){ 3 alert("arguments:",+arguments[0]); 4 } 5 } 6 test("a");//當前頁面中會顯示出一個彈出框並顯示arguments:a
所以由上面可以看出,arguments對象的使用方式和array是十分的相像的。為什么說他只是類似數組對象呢,因為他僅僅只有length屬性但並沒有array的其他屬性和方法。
當然在arguments對象中也是有一些其自己的屬性的,如下
- callee,屬性存儲的是當前的調用的函數對象。當我們使用匿名函數的時候,如果需要調用存儲當前的arguments對象的方法對象,此時可以使用當前屬性。但是在ECM5中是阻止使用這一屬性的。這樣做的原因是,函數命名來調用函數的實現是優於這種方式的。
- caller,這一屬性只有當函數正在執行的情況之下才會被定義。當然其返回的內容是當前的和toString方法是一樣的,為function的反編譯文本。但是實際上在使用的時候返回便以文本之后,js有解析成為函數對象之后執行,所以說,這一屬性實際上還是返回函數本身。但是這一屬性在ECM5中已經被刪除了。
- length屬性,是初始化的時候讀取當前函數中的參數后獲取的值。所以函數的length屬性的值其實就和arguments.length的值的大小是一樣的。
- prototype屬性,表示的是當前的function對象的原型對象。也可以了幾位當前的函數對象繼承了原型對象的屬性和方法。具體參見js原型鏈學習。
當然對於函數對象js中也是有定義一些基本方法的。
- apply方法相信你不會陌生,制定方法替換當前的this指針,冰用穿入的對象中的數據替換當前函數的參數值。上例子:
function test(){ alert("" + this); } function testTwo(a){
console.log("this:"+this); console.log("a:"+a); } testTwo.apply(test, [1]); //輸出的效果是this:function test(){ alert("" + this);} 與 a:1實際上apply是用第一個參數中的對象替換當前的函數中的this指針,並用數組參數中的數據來來替換但錢的函數調用時的參數。
- bind方法,其效果是不論當前的函數怎么調用他的this指針代表的值都是一樣的。
1 var displayArgs = function (val1, val2, val3, val4) { 2 document.write(val1 + " " + val2 + " " + val3 + " " + val4); 3 } 4 5 var emptyObject = {}; 6 7 var displayArgs2 = displayArgs.bind(emptyObject, 12, "a"); 8 9 displayArgs2("b", "c"); 10 11 // Output: 12 a b c
由上面可見實際上bind函數就有點像是綁定當前的內容和一個數據的關系。並返回一個一個可調用對象。
- call方法使用效果實際上和apply方法是一樣的,只是其后面傳遞的第二個參數不在是嚴格要求是數組。
以上就是我學習到的Function的內容,本人小白,愛生活,愛前端。