學好js,這些js函數概念一定要知道

函數創建方式###

1.聲明方式 例如:function consoleTip (){ console.log("tip!"); }
 2.表達式方式 例如:var consoleTip = function(){ console.log("tip!"); }

兩種方式的區別
 1.表達式方式適合用來定義只使用一次的函數,聲明方式定義的函數沒有這個限制,當然也不是絕對的,這個區別只適用于編碼規范上;
 2.聲明方式定義的函數可以在函數調用之前定義也可以在函數調用之后定義,而表達式方式定義的函數只能在函數調用之前定義;

函數參數###

函數參數包括形參,實參,形參就是函數定義時的參數;實參就是函數調用時傳入的參數。由于js是弱類型語言,所以js函數的形參不指定類型。

js函數的形參和實參個數可以不一致。形參個數小于實參時,未傳的形參值都是undefined,注意形參可以指定默認值,但是只能在函數體內部指定;形參個數小于實參時,在函數體內引用多余實參,必須通過實參對象arguments來獲取實參,在函數體內部arguments就是實參對象的引用,并且此時的實參對象是一個數組對象,數組對象每一項對應著函數調用時傳入的參數。

PS:實參對象有兩個特殊屬性callee和caller,其中callee屬性代指當前正在執行的函數,caller屬性代指調用當前正在執行的函數的函數,caller屬性不是標準屬性,不是所有瀏覽器都支持。使用callee屬性的典型例子就是匿名函數的遞歸調用,例如定義一個階乘函數:

var fact = function(x){ 
    if(x <= 1) {
        return 1;
    }else{
        return arguments.callee(x-1)*x;
    }
};

函數作用域###

在函數中聲明的變量(包括函數形參)在整個函數體內都是可見的,包括嵌套的函數中,在函數外部是不可見的;函數體內部定義的變量會覆蓋同名的全局變量;

函數作用域中有個特性很重要,就是“聲明提前”,意思就是在函數內部任意位置聲明的變量,在函數體內部任意位置都是可見的,這是因為js引擎在預編譯js時會把函數中所有的變量聲明都提前至函數體頂部。
例如:

var scope = "outter";
!function(){
    console.log(scope);  //undefined
    var scope = "inner";
    console.log(scope); //inner
}();
console.log(scope);  //outter

說明
undefined 由于函數作用域的聲明提前特性,這里的scope已經在函數頂部聲明,但是沒有被賦值,所以scope值為undefined
inner scope在函數體內部聲明,并且有賦值
outter  函數體內部定義的變量會覆蓋同名的全局變量,但是不影響全局變量的值

構造函數##

構造函數的用處就是用來初始化新創建的對象,例子:var ary = new Array();

構造函數與普通函數的區別
 1.函數命名上有區別,構造函數命名時通常是首字符大寫,普通函數命名時首字符小寫;
 2.調用方式的區別,構造函數是通過new關鍵字調用,而普通函數直接調用。

立即執行函數###

把函數定義和函數執行結合到一起就是立即執行函數,也叫自執行函數。

這里需要注意兩點:1.函數定義僅限于表達式方式定義的函數;2.函數執行實際上就是對函數表達式做一次運算,所以一元運算符都可以讓函數執行。

這樣的話,立即執行函數就會有多種寫法:

(function(){console.log("IIFE");}());
(function(){console.log("IIFE");})();
!function(){console.log("IIFE");}();
void function(){console.log("IIFE");}();
~function(){console.log("IIFE");}();
....

立即執行函數可以接受參數,上面的寫法都是可以的,但是編碼規范推薦第一種寫法,jQuery庫使用的就是第一種寫法。

那么自執行函數的用處有哪些呢?總結起來常用也就兩種:1.保存參數上下文環境2.作為命名空間

用處1的適用場景:循環中執行異步函數,并且函數參數隨循環變化。

/**
* 實例一
* 錯誤寫法,因為jQuery的post方法是異步的,循環十次,post方法并行跑十次,
* 循環比post方法執行要快,最終傳過去的i值都變成了10,即服務端收到index的都是10
*/
for(var i=0; i<10; i++){
    $.post(url,{index:i},function(){});
}
/**
* 正確寫法,這樣對于循環體中的立即執行函數來說,每次循環得到的參數都不同。立即執行函數
* 每執行一次都會創建一個函數上下文環境,在這個上下文環境中的變量值不受外界影響,
* 循環十次就會創建十個上下文環境,并且每個上下文環境的i值都不一樣。這樣的話,
* 雖然post方法是異步方法,但是是在每一個上下文環境中執行的,也就是說循環十次,
* post方法在十個上下文環境中分別執行了一次,post方法中使用的index參數每次都不一樣,
* 最終服務端收到的index值就是從0到9十個數值
*/
for(var i=0; i<10; i++){
    (function(index){$.post(url,{index:index},function(){});}(i));
}

/**
* 實例二   
* 錯誤寫法,最終會輸出十個10,因為循環體的語句會延時執行
*/
for(var i=0; i<10; i++){
    setTimeout(function(){console.log(i);},100);
}
        
//正確寫法,最終會輸出0到9十個數值,原理同上
for(var i=0; i<10; i++){
    (function(x){setTimeout(function(){console.log(x);},100);}(i));
}

用處2的適用場景:你需要寫一個公共模塊,這個公共模塊在很多地方都會使用,但是要保證公共模塊中使用的變量和函數不會對其它模塊造成污染,這樣的話這個公共模塊就需要一個單獨的不同于其它模塊的命名空間。

案例1:創建jQuery插件,保證創建的jQuery插件在jQuery的命名空間內都是有效的,這樣每個jQuery對象才可以使用。

(function($){
    $.fn.changeStyle = function(colorStr){
        this.css("color",colorStr);        
        return this;
    }
}(jQuery));

更多jQuery插件知識,請參見這篇文章

案例2:創建一個帶有私有變量和私有方法的對象。

var obj = (function(){
    var privateAttr,
        publicAttr;     
    function _setPriAttr(){
        privateAttr = "private";
    }       
    function getPriAttr(){
        return privateAttr;
    }       
    return {
        attr:publicAttr,            
        getAttr:function(){
            getPriAttr();
        }
    }
}());

通過這種方式創建的對象,利用立即執行函數的return語句對外暴露屬性以及方法,并且可以保證沒有對外暴露對象的屬性和方法,在對象外邊是無法訪問到的。

總結:其實用處1和用處2的原理都是一樣的,都是利用了函數作用域的概念,請仔細體會。

js閉包詳見下一篇文章,靜待!

參考資料: js權威指南

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 228,786評論 6 534
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,656評論 3 419
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 176,697評論 0 379
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,098評論 1 314
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,855評論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,254評論 1 324
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,322評論 3 442
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,473評論 0 289
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 49,014評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,833評論 3 355
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,016評論 1 371
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,568評論 5 362
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,273評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,680評論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,946評論 1 288
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,730評論 3 393
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 48,006評論 2 374

推薦閱讀更多精彩內容