函數是由事件驅動的或者當它被調用時執行的可重複使用的代碼塊,在JS中定義函數的方式有兩種:函數聲明和函數表達式。git
區分函數聲明和表達式最簡單的方法是看function關鍵字出如今聲明中的位置(不單單是一行代碼, 而是整個聲明中的位置)。若是function是聲明中的第一個詞,那麼就是一個函數聲明,不然就是一個函數表達式。github
// 函數聲明
function f1() {
//
}
// 函數表達式
var f2 = function () {
//
}
// 函數表達式
(function () {
//
})()
複製代碼
函數聲明會提高,但函數表達式不會。聲明提高在執行上下文。數組
function f() {
console.log(1);
}
f(); // 1
var f = function () {
console.log(2);
}
f(); // 2
複製代碼
由於函數聲明會提高,因此不能非函數的代碼塊中聲明函數,好比if。網絡
// 下面代碼的原始意圖是不聲明函數f,可是因爲f的提高,致使if語句無效,因此上面的代碼不會報錯
if (false) {
// 這樣聲明由於if不是塊級做用域,那麼函數會提高,不論if如何判斷f()都會生效
function f1() {
console.log(1);
}
}
f1(); // 1
// 要達到在條件語句中定義函數的目的,只有使用函數表達式
if (false) {
var f2 = function () {
console.log(2);
}
}
f2(); // TypeError: f2 is not a function
複製代碼
但我在測試時發現新版火狐、Chrome、IE11都不會在if中提高函數聲明,但IE11如下版本會,因此爲避免出錯,儘可能在if等非函數代碼塊中使用函數表達式。app
函數傳遞參數函數
JS中全部函數的參數都是按值傳遞的。學習
var a = 1;
function f1(arg) {
arg = 2;
console.log(arg); //2,參數若是是基本類型是按值傳遞,傳遞的是參數的副本,操做不影響原變量
}
f1(a);
console.log(a); // 1
var obj = {
a: 1
};
function f2(arg) {
arg.value = 2;
console.log(arg.value); //2,傳遞對象的時候,傳遞對象的引用的副本,改變參數會改變原參數
}
f2(obj);
console.log(obj.a) // 2
var obj2 = {
value: 1
};
function f3(arg) {
arg = { // 函數內部重寫參數,這下變量引用的就是一個局部變量
a: 2
};
console.log(arg.a); //2,傳遞引用參數副本,可是又從新給參數賦值,切斷原來的引用,因此原有引用爲改變
}
f3(obj2);
console.log(obj2.a) // 1
複製代碼
函數屬性測試
函數屬性包括:length和prototypethis
length,函數的length屬性是隻讀屬性,函數定義時的形參個數即一般也是函數調用時指望傳入函數的參數個數。spa
function add(a, b) {
return a + b;
}
add.length // 2,函數聲明時形參長度
複製代碼
prototype,每一個函數都包含一個prototype屬性,這個屬性是指向一個對象的引用,這個對象稱爲「原型對象」。每一個函數都包含不一樣的原型對象。當函數用作構造函數時,新建立的對象會從原型對象上繼承屬性。
函數內部屬性:arguments和this
arguments,arguments是一個類數組對象,包含傳入函數的全部參數,arguments的主要用途是保存函數參數。
function add(a, b) {
return arguments[0] + arguments[1];
}
add(1, 2); // 3
複製代碼
this,this引用的是函數據以執行的環境對象,關於this請點這裏this
var a = {
name: 'a',
sayName: function () {
console.log(this.name);
}
};
a.sayName(); // 'a'
複製代碼
函數方法
每一個函數都包含兩個非繼承而來的方法:apply()和call()。這兩個方法的用途都是在特定的域中調用函數,其真正強大之處在於可以擴充函數賴以運行的做用域,ES5又新增bind()方法。
關於apply、call和bind請點這裏this
由於函數也是對象,因此函數也有toString()方法,返回函數的字符串形式。
匿名函數
函數聲明必需要有標識符名稱,但函數表達式能夠不寫標識符,這樣的函數稱爲匿名函數。
// 匿名函數賦值給變量
var f = function () {
//
}
// 匿名函數自執行,自執行後內部聲明的局部變量和函數會被銷燬
(function () {
//
})()
// 匿名函數不會自執行,會報錯,這是由於這是一個函數聲明,函數聲明後邊不能跟圓括號,函數表達式後邊能夠跟圓括號
function () {
//
}()
複製代碼
寫在最後:
我只是一個自學JS的初學者,筆記是學習時各處收集的,有一些是我本身的理解。可是很多知識來自分享到網絡的大神們,由於實在不知道我在哪裏使用了誰的文章,因此只能統一的表達一下個人感謝! 文章裏邊可能有的地方會有錯誤,若是發現,能夠留言提醒我。