函數(shù)的聲明
- function關鍵字
- 可選名稱(有效的Javascript標識符)
- 括號內(nèi)部,一個以逗號分隔的參數(shù)列表(有效的Javascript標識符,列表可以為空)
- 函數(shù)體,包含在大括號內(nèi)的一系列Javascript語句(函數(shù)體可以為空)
//在全局作用域下定義一個函數(shù)
function a(){}
console.log(typeof window.a==="function"); // ture window對象上的同名屬性會引用這個函數(shù)
console.log(a.name==="a"); // true 所有函數(shù)都有一個name屬性,保存該函數(shù)名稱的字符串
//創(chuàng)建一個匿名函數(shù)并賦值給變量b
var b = function (){};
console.log(typeof window.b==="function"); // ture
console.log(b.name==="b"); // true 在舊瀏覽器下這樣定義的函數(shù)的name屬性為空或者undefined
//創(chuàng)建一個匿名函數(shù)并引用到window對象的一個屬性
window.c=function(){};
console.log(typeof window.c==="function"); // true
console.log(c.name===""); // true 在舊瀏覽器下這樣定義的函數(shù)的name屬性為undefined
//在全局作用域下創(chuàng)建outer函數(shù),并在內(nèi)部創(chuàng)建inner函數(shù)
function outer(){
console.log(typeof inner==="function"); // true 在inner創(chuàng)建之前可以訪問到inner
function inner(){}
console.log(typeof inner==="function"); // true 在inner創(chuàng)建之后可以訪問到inner
console.log(typeof window.inner==="undefined"); // true inner沒有被綁定到全局對象上去
}
//創(chuàng)建一個函數(shù)并引用到window對象的一個屬性
window.e=function d(){};
console.log(e.name==="d"); // true 這樣創(chuàng)建的函數(shù)只能使用e來調(diào)用,但它的name屬性是函數(shù)本身的字面量名稱
作用域和函數(shù)
函數(shù)可以在其作用域范圍內(nèi)提前被引用,但變量不行。
函數(shù)調(diào)用
- 作為函數(shù)進行調(diào)用
- 作為一個對象在對象上進行調(diào)用
- 作為構造器進行調(diào)用,創(chuàng)建一個新對象
- 通過apply()或call()方法進行調(diào)用
//定義一個包含參數(shù)的函數(shù)
function f(a,b,c){}
f(1); // 當參數(shù)數(shù)量少于定義的形參執(zhí)行函數(shù)時,1會被賦值給a,而b、c會被賦值為undefined
f(1,2,3,4,5); // 當參數(shù)數(shù)量多于定義的形參執(zhí)行函數(shù)時,1,2,3會被分別賦值給a,b,c,而4,5不會賦值給任何形參
所有函數(shù)調(diào)用都會傳遞兩個隱式參數(shù):arguments和this。
arguments參數(shù)是傳遞給函數(shù)的所有參數(shù)的一個集合,具有l(wèi)ength屬性,可以使用for對其進行遍歷,但不是真正的Javascript數(shù)組,無法使用數(shù)組的方法,是一個類似數(shù)組的結構,只擁有數(shù)組的某些特性。
this參數(shù)引用了與該函數(shù)調(diào)用進行隱式關聯(lián)的一個對象,稱之為:函數(shù)上下文。this的指向依賴于函數(shù)的調(diào)用方式,即便調(diào)用的函數(shù)相同,調(diào)用的方式不一樣,this的指向也會不一樣。
函數(shù) “作為函數(shù)” 調(diào)用
當一個函數(shù)以 “作為函數(shù)” 的方式進行調(diào)用時,表示應用了()操作符的表達式,并且沒有將函數(shù)作為對象的一個屬性。例如:
function a(){ return this }
a();
console.log(a()===window); // true
var b=function (){ return this };
b();
console.log(a()===window); // true
//以這種方式調(diào)用時,函數(shù)的上下文是全局上下文window對象,及this的指向為window對象
函數(shù) “作為方法” 調(diào)用
當一個函數(shù)以 “作為方法” 的方式進行調(diào)用時,表示函數(shù)被賦值給一個對象的屬性,并使用引用該函數(shù)的屬性進行調(diào)用,例如:
var a={};
a.b=function (){ return this };
a.b(); // 以這種方式調(diào)用時,函數(shù)的上下文是當前對象
console.log(a.b()===a); // ture
其實函數(shù) “作為函數(shù)” 的調(diào)用方式是 “作為方法” 調(diào)用方式的一種特殊情況。 “作為函數(shù)” 的調(diào)用時,函數(shù)其實是綁定在window對象上的,window對象就是當前函數(shù)的上下文。省略了window對象調(diào)用的方式,直接使用函數(shù)字面量進行調(diào)用。
面向?qū)ο笞兂傻幕靖拍钪唬褪俏覀兛梢栽谌我夥椒ㄖ?,通過this的指向來引用該方法所屬的對象。
函數(shù)作為構造器調(diào)用
function A(){ this.b=function(){ return this }}
var c=new A(); // 在函數(shù)調(diào)用前使用new關鍵字表示函數(shù)作為構造器進行調(diào)用
console.log(c.b()===c); // true 構造函數(shù)創(chuàng)建的實例中this指向當前對象。
作為構造器調(diào)用時,會發(fā)生以下行為:
- 創(chuàng)建一個新的空對象。
- 將新對象的this參數(shù)傳遞給構造器函數(shù),從而新對象的函數(shù)上下文成為構造器的函數(shù)上下文。
- 如果沒有顯示的返回值,則新對象作為構造器的返回值進行返回(任何干擾這種意圖的都不適合作為構造器)。
一般的函數(shù)和方法以小寫字母開頭,構造器函數(shù)以大寫字母開頭。
使用apply()和call()方法進行調(diào)用
Javascript中函數(shù)也可以像對象一樣擁有方法和屬性,每個函數(shù)都有apply()和call()方法。
通過apply()調(diào)用函數(shù),需要傳入兩個參數(shù),一個是作為函數(shù)上下文的對象,另一個是函數(shù)參數(shù)所組成的數(shù)組。call()方法與之類似,唯一不同的是call()方法給函數(shù)傳入的是參數(shù)列表,而不是將所有參數(shù)作為一個數(shù)組傳入。
function x(a,b){
this.y=a+b;
}
var a={};
var b={};
x.apply(a,[1,2]);
x.call(b,1,2);
console.log(a.y); // 3 此時x函數(shù)中的this被綁定為a對象
console.log(b.y); // 3 此時x函數(shù)中的this被綁定為b對象
Javascript是函數(shù)式編程語言,函數(shù)式程序的構件塊而不是命令式語句。
//一般的命令式編程
function (list){
for(var i=0;i<list.length;i++){
/* 每一項需要執(zhí)行的代碼 */
}
}
//函數(shù)式編程
for(var i=0;i<list.length;i++){
fun(list[n]);
}