除去第三章說的 var 申明一個變量外,還可以用
function
申明一個函數對象
function foo(){}
function
,見名知意就是函數,既然是函數就可以用來運算。比如最簡單的加法
function add(a,b){
var result = a+b;
return result ;
}
先說一下函數的主體結構。
-
function
申明接下來是一個函數對象 -
add
說明了這個函數的名稱,如果不寫就是一個匿名函數 <anonymous> -
()
代表這個函數的參數部分 -
a、b
在參數部分有兩個參數,分別是a和b,如果沒有參數就省略4,但是3還是要保留。 -
{ }
這里不是對象{}
,而代表的是函數的主體內容。 -
var result = a+b;
實際分解為:
var result;
result = a+b;
-
return
是這個函數結尾的部分,返回后面跟隨的執行結果result。假如這個函數沒有返回值可以不寫。
調用該add函數時,使用
add(1,2);
就會得到結果 3 。
作用域和變量提升
在函數里面有一個作用域【scope】[1]的概念,同時還有一個var
關鍵字的變量提升,變量提升和作用域是息息相關的。
其實變量提升我已經寫下來了,反觀add第六步,就是變量提升分解示意。
變量提升后的完整的第六步:
function add(a,b){
var result;
result = a+b;
return result ;
}
變量提升將變量的申明部分提升到作用域(函數體)的頂部,也就是執行時函數體的第一條語句。
為什么會有這種操作?這是因為js語言設計缺陷,允許不申明就使用:
s = 1;
直接的賦值,并沒有用var或者function聲明這個s。這在別的語言中,很顯然是不符合先申明再使用的規范的。并且,沒有申明直接使用的變量他的作用域不是當前的函數體,而是頂級的宿主對象[2],存在變量的作用域提升,會給開發者造成不必要的問題。所以,為了防止這種現象,在作用域頂部,引入 'use strict'
嚴格模式,嚴格檢查當前作用域未申明的情況。
function sub(){
'use strict'
s = 1;
}
在調用 sub函數是就會報引用錯誤 ReferenceError: s is not defined
引申:在函數式編程中,提出了“函數是一等公民”的思想,強調函數式編程的純凈[3]
不能不說 this
默認情況下,this指向當前函數的擁有者。
在瀏覽器下:
function owner(){
return this;
}
owner() ;// Window
即使這個函數寫在另一個函數體內
function owner(){
return function(){
return this;
};
}
owner()() ;// Window
重要的 arguments
js的函數在執行時,所有的參數列表都是由arguments這個內置屬性管控的,所有的參數列表都是可以通過arguments來取值。
function argsTest(){
return arguments.length;
}
argsTest(1,2,3) // 3
argsTest(1,2) // 2
argsTest() // 0
這樣做是因為js并不能函數重載[4],同名函數只能定義一次,多次定義之后就會直接覆蓋:
function reloadFn(){}
function reloadFn(name){}
其實這個可以看作
var reloadFn;
reloadFn = function(){}
reloadFn = function(name){}
所以只會保留最后一次定義的值,這樣就不難理解了。因此對于js來說沒有重載的必要,但是又想實現重載的功能,所以就有了arguments。
arguments本身是一個類似數組,但是沒有數組的某些函數。不過可以通過 Array.prototype.slice.call(arguments) 重新構建一個數組。這樣,就可以當作數組來