看犀牛書的筆記——函數(上)

12db93510fb30f24a1985094ce95d143ac4b03fd.jpg

函數是什么?在JavaScrit中函數是一段代碼,只定義一次,但可以被執行或調用任意次。當然不是上圖的含樹。對于函數我想干嘛用的大家都知道,這里沒什么好贅述的。
在深入的學習之前,我先了解了一下。做了一點知識預覽。

  • 函數是參數化的: function(x,y){}意思就是()里面的可以傳參數,然后拿來用。函數聲明的時候()里面的參數叫形參,調用的時候()里面的參數叫實參(除了實參,調用的時候還會擁有一個本次調用的上下文this)。
  • 如果函數作為對象的屬性,就稱他為對象的方法。當調用這個函數的時候他的上下文就是這個對象,即this的值。用于初始化一個對象的函數叫構造函數
  • 函數即對象,所以可以像使用對象那樣使用他,比如:給他添加屬性、把他賦值給變量、作為實參傳遞給其他函數等等。
  • 函數中可以嵌套函數,閉包就是嵌套函數的功勞啊。

函數的定義

函數的定義有兩種方法:

  • 函數語句
function add(x,y){
return x+y;
}

上面的就是函數語句定義的函數。其實就是創建了一個新的函數對象,并將其賦值給變量add。函數的名字實際是看不見的,add僅僅是變量的名字。函數還可以賦值給其他變量var a = add; a(1,2);

  • 函數表達式
    書中原文

用函數表達式來定義函數指適用于它作為一個大的表達式的一部分,比如在賦值和調用中定義函數

/*這就相當于將函數add賦值給了a,如果我們要使用函數add就不能再直接add(2,4)了,變成了a(2,4)。
  為何呢?因為這時的函數add()不再是一個全局的對象了。
*/
var a = function add(x,y){
return x+y;
}
/*這里函數的名稱被省略了。
為何要省略?1、相當劃出一塊私有作用域,避免數據污染。2、執行完就銷毀,避免內存長駐。
什么情況下不省略?需要指代自己的時候 */
var b = function (x,y){
return x-y;//return會使函數停止,所以return后面的語句都不會執行;
console.log('look at me!');
}
var f = function fact(x){
if(X=1)return 1;else return x*fect(x-1);//這里就指代了自己
}
//定義后立即調用,這是一種很新奇的寫法,但是用到的場景太少了。最外層的括號不能去到,去到就會被當作是定義函數啦。這種寫法我還不能給出合理的解釋,以后補充。
var c = (function(x,y){return x*y}(2,4));

上面代碼塊的注釋很重要!!!還需要注意的是,函數聲明語句會被提前,但是用函數表達式聲明函數,變量的聲明提前了,但是變量的賦值卻沒有提前,所以在聲明前調用會報錯。

函數調用

函數在定義的時候是不會執行的,只有調用函數時才會執行。調用函數有4種方法。

  • 作為函數調用
function add (x,y) {
return x+y;
}
var a = add; //將函數add賦值給變量a
//以下都是作為函數調用
add(1,2)
a(1,2)
var b =(function(x,y){return x+y;}(1,2))
  • 作為方法
    一個方法無非就是保存在一個對象的屬性里的函數。比如有一個對象a,a對象有一個屬性b,有一個方法f。那么a.b=f;就把f函數賦值給了a對象的屬性b。就等于給a對象定義了方法b。
//作為方法調用
      a.b();
      a.['b']()//這種寫法也是可以的
//如果需要傳參
a.b(12,22);

前面說過,作為方法調用上下文就是它所屬的對象。即this指向對象。

var a ={
    b:1,
    c:2,
    add: function(){return this.b+this.c;}
}
a.add();//這里返回3

需要注意的是this是一個關鍵字,不是變量也不是屬性名。不可給this賦值。
this沒有作用域的限制,嵌套的函數沒有辦法繼承this,這是就需要將this賦值給一個變量。通常都用self作為變量名。

var o ={
    a: 1,
    add: function(){
          var self = this;
          function(){
                return self .a;//這里如果使用this,那么this不是全局對象就是undefined
              }
    }
}
  • 構造函數調用
    如果函數或者方法調用之前帶有關鍵字new,它就構成了構造函數調用。
    構造函數是什么?我更傾向于這樣的一種解釋——JavaScript中沒有類,只有new運算來模擬類,構造函數無從談起。在其他語言中,比如java,構造方法用于返回該類的對象。
    附上連接http://www.2cto.com/kf/201402/281841.html
    這里說的很詳細。
    如果構造函數不需要傳參,那么下面兩種寫法等價:
var a = new Object();
var a = new Object;
  • 使用call()和apply()間接調用
    這種情況在以后call和apply的介紹時一并介紹。

函數的實參和形參

前面說過形參就是函數定義是()中的參數,實參就是調用函數時()中實際傳遞的參數。JavaScrit在定義和調用時都沒有指定參數的類型。調用時甚至不檢查傳入的參數個數。
用例子說明一切
假設有這么一個函數:

function add(x,y){
  return x+y;
}

1、當實參比形參少的時候add(1);,這時候x=1,而y將被設置為undefined。為了避免這樣的情況。應該給省略的參數賦一個合理的默認值。

function add(x,y){
  if(y === undefined) y = 0;
//還有一種更簡潔的寫法  y=y || 0;
  return x+y;
}

2、當實參比形參多的時候add(1,2,3);,形參只有兩個只能對應前兩個實參,第三個實參將被忽略。這個時候,就要用到arguments了。
arguments并不是什么高深的東西,就兩句話——arguments指向實參對象的引用,是一個類數組對象(是對象不是數組)。可以像使用數組一樣使用他。

function add(x,y){
  var a = 0;
  for(var i = 0;i<arguments.length;i++){
      a += arguments[i];
  }
  return a;
}

上面的代碼不管傳多少個參數都可以將所有實參的和返回了,但如果我想要判斷我傳入的實參的類型呢?比如我只想將數字相加,其他都滾蛋。

function add(x,y){
  var a = 0;
  for(var i = 0;i<arguments.length;i++){
    if(argument[i].isNumber()){
            a += arguments[i];
      }
  }
  return a;
}

像這種函數,也叫做不定實參函數。這種函數的實參個數不能為零(你要是一個實參都不傳那還用個卵的arguments)。arguments[]對象最適合的應用場景是在這樣一類函數中,這類函數包含固定個數的命名和必須參數,以后隨個數不定的可選參數。

  • callee(被召者)和caller(呼叫者)屬性
    這兩個屬性是實參對象arguments的屬性。這兩個屬性在嚴格模式下讀寫都會產生類型錯誤(在webstorm里會飄紅)。書上說:callee指代當前正在執行的函數。聽著有點像call;caller指代調用當前正在執行的函數的函數。沒聽懂。附上一個連接便于理解:http://www.cnblogs.com/dingyuanxin/p/4176310.html

實參

這里還是詳細的說一下實參。當函數形參超過三個時,要記住正確的順序還是挺麻煩的,那在多個形參傳遞的時候,應該怎么避免這種情況呢?——傳一個對象。例如:

function  getPersonInfo(name,age,sex) {
    console.log(name+age+sex);
}
//要是我這樣傳,name就成了18,age成了王二了。
getPersonInfo('18','王二','男');
//所以可以這樣寫
function getPersonInfo(args){
    console.log(args.name+args.age+args.sex);
}
getPersonInfo({name:'王二',age'18',sex:'男'});

實參類型
實參可以是任意類型——對象、函數、字符串、null、undefined等等。有些時候,為了確保函數執行不報錯,會對實參的類型進行判斷,這樣的判斷很重要但經常被忽略。

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

推薦閱讀更多精彩內容