function add(x, y){ return x + y; }
上述函數定義以下:javascript
function
指出這是一個函數定義;add
是函數的名稱;(x, y)
括號內列出函數的參數,多個參數以,
分隔;{}
之間的代碼是函數體,能夠包含若干語句,甚至能夠沒有任何語句。函數體內部的語句在執行時,一旦執行到return
時,函數就執行完畢,並將結果返回。
若是沒有return
語句,函數執行完畢後也會返回結果,只是結果爲undefined
。html
JavaScript的函數也是一個對象,函數名能夠視爲指向該函數的變量。所以,函數也能夠像下面這樣定義。java
var add = function (x, y){ return x + y; }
這種狀況下,function (x, y){}
是一個匿名函數,它沒有函數名。可是,這個匿名函數賦值給了變量add
,因此,經過變量add
就能夠調用該函數。數組
調用函數時,按順序傳入參數便可。閉包
add(1, 2); // 3
關鍵字arguments
只在函數內部起做用。咱們經過arguments
能夠得到調用者傳入的全部參數。事實上,arguments
最經常使用於判斷傳入參數的個數。app
function add(x, y){ for(let i = 0; i < arguments.length; i++){ console.log(arguments[i]); } return x + y; } console.log(add(1,5)); // 1 5 6
在JavaScript中,用var
聲明的變量是有做用域的。
若是一個變量在函數體內聲明,則該變量的做用域是整個函數體。
若是兩個不一樣的函數各自聲明瞭一個同名變量,那麼這兩個變量是相互獨立的,互不影響。
因爲JavaScript的函數能夠嵌套,內部函數能夠訪問外部函數定義的變量,反過來則不行。
JavaScript的函數在查找變量時從自身函數定義開始,從"內"向"外"查找。
若是內部函數定義了與外部函數重名的變量,則內部函數的變量將"屏蔽"外部函數的變量。函數
JavaScript會把變量聲明提高到頂部。post
function foo(){ console.log(x); // 不報錯 var x = 'Hello'; } // 等同於 function foo(){ var x; console.log(x); x = 'Hello'; }
在一個對象中綁定函數,稱爲這個對象的方法。學習
var me = { name: '張三', birth: 1994, age: function(){ var y = new Date().getFullYear(); return y - this.birth; } }; console.log(me.age()); // 25
若是以對象的方法形式調用me.age()
,函數age()
的this
指被調用的對象me
。網站
apply
、call
、bind
var obj = {birth: 1990}; console.log(me.age.call(obj)); // 29 console.log(me.age.apply(obj)); // 29 let bind = me.age.bind(obj); console.log(bind()); // 29
apply
、call
和bind
這三個函數的做用是改變函數執行時的上下文,即改變函數運行時的this
的指向。
apply
和call
改變了函數的this
上下文後便執行該函數,bind
則返回改變了上下文後的一個函數。apply
和call
的第一個參數都是要改變上下文的對象,而call
從第二個參數開始以參數列表的形式展示,apply
把除了改變上下文對象的參數放在一個數組裏面做爲它的第二個參數。let arr1 = [1, 2, 10, 4]; //例子:求數組中的最值 console.log(Math.max.call(null, 1, 2, 10, 4)); // 10 console.log(Math.max.call(null, arr1)); // NaN console.log(Math.max.apply(null, arr1)); // 10
JavaScript的函數接收變量做爲參數,而函數名能夠視爲指向該函數的變量。所以,一個函數能夠接收另外一個函數做爲參數。這種函數被稱爲高階函數。
function add(x, y, f) { return f(x) + f(y); } console.log(add(-5, 6, Math.abs)); // 11
內置對象Array
提供了一些高階函數:
map
reduce
filter
sort
every
find
findIndex
forEach
相關閱讀:JavaScript Array 對象
高階函數除了能夠接受函數做爲參數外,還能夠把函數做爲結果值返回。
/* function lazy_sum(arr) { var sum = function () { return arr.reduce(function (x, y) { return x + y; }); } return sum; } */ function lazy_sum(arr) { return function () { return arr.reduce(function (x, y) { return x + y; }); }; } var f = lazy_sum([1, 2, 3, 4, 5]); console.log(f()); // 15
在lazy_sum
函數中定義了函數sum
,sum
函數能夠訪問lazy_sum
函數的變量arr
(內部函數能夠訪問外部函數,參數能夠看做函數中聲明的變量)。當一個函數返回了一個函數後,相關的變量都保存在返回的函數中。
返回的sum
函數依然保持對lazy_sum
函數的做用域的引用,這個引用就叫做閉包。
注意:返回的函數沒有當即執行,而是直到調用了f()
才執行。
使用閉包時要牢記一點是:返回函數不要引用任何循環變量,或者後續會發生變化的變量。
再看另外一個例子。
var buildMultiplier = function(x) { return function(y) { return x * y; } } var double = buildMultiplier(2); var triple = buildMultiplier(3); console.log(double(3)); // 6 console.log(triple(3)); // 9
參考: