JavaScript 函數(shù)定義
function functionName(parameters) {
執(zhí)行的代碼
}
分號是用來分隔可執(zhí)行JavaScript語句。
由于函數(shù)聲明不是一個(gè)可執(zhí)行語句,所以不以分號結(jié)束。
函數(shù)表達(dá)式
JavaScript 函數(shù)可以通過一個(gè)表達(dá)式定義。
函數(shù)表達(dá)式可以存儲在變量中:
var x = function (a, b) {return a * b};
Function() 構(gòu)造函數(shù)
在以上實(shí)例中,我們了解到函數(shù)通過關(guān)鍵字 function 定義。
函數(shù)同樣可以通過內(nèi)置的 JavaScript 函數(shù)構(gòu)造器(Function())定義。
var myFunction = new Function("a", "b", "return a * b");
var x = myFunction(4, 3);
var myFunction = function (a, b) {return a * b};
var x = myFunction(4, 3);
函數(shù)提升
提升(Hoisting)是 JavaScript 默認(rèn)將當(dāng)前作用域提升到前面去的的行為。
提升(Hoisting)應(yīng)用在變量的聲明與函數(shù)的聲明。
myFunction(5);
function myFunction(y) {
return y * y;
}
自調(diào)用(立即執(zhí)行)函數(shù)
函數(shù)表達(dá)式可以 "自調(diào)用"。
自調(diào)用表達(dá)式會自動調(diào)用。
如果表達(dá)式后面緊跟 () ,則會自動調(diào)用。
不能自調(diào)用聲明的函數(shù)。
通過添加括號,來說明它是一個(gè)函數(shù)表達(dá)式
(function () {
var x = "Hello!!"; // 我將調(diào)用自己
})();
函數(shù)是對象
在 JavaScript 中使用 typeof 操作符判斷函數(shù)類型將返回 "function" 。
但是JavaScript 函數(shù)描述為一個(gè)對象更加準(zhǔn)確。
JavaScript 函數(shù)有 屬性 和 方法。
arguments.length 屬性返回函數(shù)調(diào)用過程接收到的參數(shù)個(gè)數(shù)
function myFunction(a, b) {
return arguments.length;
}
toString() 方法將函數(shù)作為一個(gè)字符串返回
function myFunction(a, b) {
return a * b;
}
var txt = myFunction.toString();
函數(shù)定義作為對象的屬性,稱之為對象方法。
函數(shù)如果用于創(chuàng)建新的對象,稱之為對象的構(gòu)造函數(shù)。
箭頭函數(shù)
ES6 新增了箭頭函數(shù)。
箭頭函數(shù)表達(dá)式的語法比普通函數(shù)表達(dá)式更簡潔。
(參數(shù)1, 參數(shù)2, …, 參數(shù)N) => { 函數(shù)聲明 }
(參數(shù)1, 參數(shù)2, …, 參數(shù)N) => 表達(dá)式(單一)
// 相當(dāng)于:(參數(shù)1, 參數(shù)2, …, 參數(shù)N) =>{ return 表達(dá)式; }
當(dāng)只有一個(gè)參數(shù)時(shí),圓括號是可選的
(單一參數(shù)) => {函數(shù)聲明}
單一參數(shù) => {函數(shù)聲明}
沒有參數(shù)的函數(shù)應(yīng)該寫成一對圓括號
() => {函數(shù)聲明}
// ES5
var x = function(x, y) {
return x * y;
}
// ES6
const x = (x, y) => x * y;
有的箭頭函數(shù)都沒有自己的 this。 不適合頂一個(gè) 對象的方法。
當(dāng)我們使用箭頭函數(shù)的時(shí)候,箭頭函數(shù)會默認(rèn)幫我們綁定外層 this 的值,所以在箭頭函數(shù)中 this 的值和外層的 this 是一樣的。
箭頭函數(shù)是不能提升的,所以需要在使用之前定義。
使用 const 比使用 var 更安全,因?yàn)楹瘮?shù)表達(dá)式始終是一個(gè)常量。
如果函數(shù)部分只是一個(gè)語句,則可以省略 return 關(guān)鍵字和大括號 {},這樣做是一個(gè)比較好的習(xí)慣
JavaScript 函數(shù)參數(shù)
函數(shù)顯式參數(shù)在函數(shù)定義時(shí)列出。
函數(shù)隱式參數(shù)在函數(shù)調(diào)用時(shí)傳遞給函數(shù)真正的值。
參數(shù)規(guī)則
- JavaScript 函數(shù)定義顯式參數(shù)時(shí)沒有指定數(shù)據(jù)類型。
- JavaScript 函數(shù)對隱式參數(shù)沒有進(jìn)行類型檢測。
- JavaScript 函數(shù)對隱式參數(shù)的個(gè)數(shù)沒有進(jìn)行檢測。
默認(rèn)參數(shù)
ES5 中如果函數(shù)在調(diào)用時(shí)未提供隱式參數(shù),參數(shù)會默認(rèn)設(shè)置為:undefined
有時(shí)這是可以接受的,但是建議最好為參數(shù)設(shè)置一個(gè)默認(rèn)值:
function myFunction(x, y) {
if (y === undefined) {
y = 0;
}
}
如果函數(shù)調(diào)用時(shí)設(shè)置了過多的參數(shù),參數(shù)將無法被引用,因?yàn)闊o法找到對應(yīng)的參數(shù)名。 只能使用 arguments 對象來調(diào)用。
ES6 函數(shù)可以自帶參數(shù)
ES6 支持函數(shù)帶有默認(rèn)參數(shù),就判斷 undefined 和 || 的操作
function myFunction(x, y = 10) {
// y is 10 if not passed or undefined
return x + y;
}
myFunction(0, 2) // 輸出 2
myFunction(5); // 輸出 15, y 參數(shù)的默認(rèn)值
arguments 對象
JavaScript 函數(shù)有個(gè)內(nèi)置的對象 arguments 對象。
argument 對象包含了函數(shù)調(diào)用的參數(shù)數(shù)組。
通過值傳遞參數(shù)
在函數(shù)中調(diào)用的參數(shù)是函數(shù)的隱式參數(shù)。
JavaScript 隱式參數(shù)通過值來傳遞:函數(shù)僅僅只是獲取值。
如果函數(shù)修改參數(shù)的值,不會修改顯式參數(shù)的初始值(在函數(shù)外定義)。
隱式參數(shù)的改變在函數(shù)外是不可見的。
通過對象傳遞參數(shù)
在JavaScript中,可以引用對象的值。
因此我們在函數(shù)內(nèi)部修改對象的屬性就會修改其初始的值。
修改對象屬性可作用于函數(shù)外部(全局變量)。
修改對象屬性在函數(shù)外是可見的。
JavaScript 函數(shù)調(diào)用
JavaScript 函數(shù)有 4 種調(diào)用方式。
每種方式的不同在于 this 的初始化。
this 關(guān)鍵字
一般而言,在Javascript中,this指向函數(shù)執(zhí)行時(shí)的當(dāng)前對象。
注意 this 是保留關(guān)鍵字,你不能修改 this 的值。
調(diào)用 JavaScript 函數(shù)
函數(shù)中的代碼在函數(shù)被調(diào)用后執(zhí)行。
function myFunction(a, b) {
return a * b;
}
myFunction(10, 2); // myFunction(10, 2) 返回 20
以上函數(shù)不屬于任何對象。但是在 JavaScript 中它始終是默認(rèn)的全局對象。
在 HTML 中默認(rèn)的全局對象是 HTML 頁面本身,所以函數(shù)是屬于 HTML 頁面。
在瀏覽器中的頁面對象是瀏覽器窗口(window 對象)。以上函數(shù)會自動變?yōu)?window 對象的函數(shù)。
myFunction() 和 window.myFunction() 是一樣的
全局對象
當(dāng)函數(shù)沒有被自身的對象調(diào)用時(shí) this 的值就會變成全局對象。
在 web 瀏覽器中全局對象是瀏覽器窗口(window 對象)。
函數(shù)作為全局對象調(diào)用,會使 this 的值成為全局對象。
使用 window 對象作為一個(gè)變量容易造成程序崩潰。
函數(shù)作為方法調(diào)用
在 JavaScript 中你可以將函數(shù)定義為對象的方法。
var myObject = {
firstName:"John",
lastName: "Doe",
fullName: function () {
return this.firstName + " " + this.lastName;
}
}
myObject.fullName(); // 返回 "John Doe"
函數(shù)作為對象方法調(diào)用,會使得 this 的值成為對象本身
使用構(gòu)造函數(shù)調(diào)用函數(shù)
如果函數(shù)調(diào)用前使用了 new 關(guān)鍵字, 則是調(diào)用了構(gòu)造函數(shù)。
這看起來就像創(chuàng)建了新的函數(shù),但實(shí)際上 JavaScript 函數(shù)是重新創(chuàng)建的對象
// 構(gòu)造函數(shù):
function myFunction(arg1, arg2) {
this.firstName = arg1;
this.lastName = arg2;
}
// This creates a new object
var x = new myFunction("John","Doe");
x.firstName; // 返回 "John"
構(gòu)造函數(shù)的調(diào)用會創(chuàng)建一個(gè)新的對象。新對象會繼承構(gòu)造函數(shù)的屬性和方法。
構(gòu)造函數(shù)中 this 關(guān)鍵字沒有任何的值。
this 的值在函數(shù)調(diào)用實(shí)例化對象(new object)時(shí)創(chuàng)建。
作為函數(shù)方法調(diào)用函數(shù)
在 JavaScript 中, 函數(shù)是對象。JavaScript 函數(shù)有它的屬性和方法。
call() 和 apply() 是預(yù)定義的函數(shù)方法。 兩個(gè)方法可用于調(diào)用函數(shù),兩個(gè)方法的第一個(gè)參數(shù)必須是對象本身。
function myFunction(a, b) {
return a * b;
}
myObject = myFunction.call(myObject, 10, 2); // 返回 20
function myFunction(a, b) {
return a * b;
}
myArray = [10, 2];
myObject = myFunction.apply(myObject, myArray); // 返回 20
兩個(gè)方法都使用了對象本身作為第一個(gè)參數(shù)。 兩者的區(qū)別在于第二個(gè)參數(shù): apply傳入的是一個(gè)參數(shù)數(shù)組,也就是將多個(gè)參數(shù)組合成為一個(gè)數(shù)組傳入,而call則作為call的參數(shù)傳入(從第二個(gè)參數(shù)開始)。
在 JavaScript 嚴(yán)格模式(strict mode)下, 在調(diào)用函數(shù)時(shí)第一個(gè)參數(shù)會成為 this 的值, 即使該參數(shù)不是一個(gè)對象。
在 JavaScript 非嚴(yán)格模式(non-strict mode)下, 如果第一個(gè)參數(shù)的值是 null 或 undefined, 它將使用全局對象替代。
通過 call() 或 apply() 方法你可以設(shè)置 this 的值, 且作為已存在對象的新方法調(diào)用