前面曾經(jīng)提到過,ECMAScript中的函數(shù)是對象,因此函數(shù)也有屬性和方法。每個函數(shù)都包含兩個屬性;length和prototype。其中,length屬性表示函數(shù)希望接收的命名參數(shù)的個數(shù),如下面的例子所示:
function sayName (name){
alert(name);
function sum (numl,num2){
return numl+num2;
function sayHi(){
alert("hi");
alert(sayName.length); //1
alert(sum.length)j //2
alert(sayHi.length); //0
}
以上代碼定義了3個函數(shù),但每個函數(shù)接收的命召參數(shù)個數(shù)不同。南昌網(wǎng)絡(luò)公司技術(shù)人員要講的是,首先,sayName()函數(shù)定義了一個參數(shù),因此其length屬性的值為1。類似地,sum()函數(shù)定義了兩個參數(shù),結(jié)果其length屬性中保存的值為2。而sayHi()沒有命名參數(shù),所以其length值為0。
在ECMAScript核心所定義的全部yp性中,逞霍黔嘉緊的就要數(shù)prototype屬性了。對于ECMAScript中的引用類型而言,prototype是保存琴幫咿琵疆霹霸哥薪j(luò)譬換句話說,諸如toString()和valueOf()等方法實際上都保存在prot。type名下,只不過是通過各自對象的實例訪問罷了。在創(chuàng)建自定義引用類型以及實現(xiàn)繼承時,prototype屬性的作用是極為重要的
每個函數(shù)都包含兩個非繼承而來的方法:apply()和call()。這兩個方法的用途都是在特定的作用域中調(diào)用函數(shù),實際上等于設(shè)置函數(shù)體內(nèi)this對象的值。首先,apply()方法接受兩個參數(shù):一個是在其中運行函數(shù)的作用域,另一個是參數(shù)數(shù)組。其中,第二個參數(shù)可以是Array的實例,也可以是arguments對象。例如:
function sum (numl, num2){
return numl+num2:
}
function callSuml (numl, num2){
return sum.apply( this,arguments); //傳入arguments對象
}
function callSum2 (numl, num2){
return sum.apply( this,[numl,num2]); //傳入數(shù)組
}
alert (callSuml(10,10))j //20
alert( callSum2 (10, 10)); //20
在上面這個例子中,callSuml()在執(zhí)行sum()函數(shù)時傳人了this作為作用域(因為是在全局作用域中調(diào)用的,所以傳人的就是window對象)和arguments對象。而callSLun2同樣也調(diào)用了sum()函數(shù),但它傳人的則是this和一個參數(shù)數(shù)組。這兩個函數(shù)都會正常執(zhí)行并返回正確的結(jié)果。
call()方法與apply()方法的作用相同,它們的區(qū)別僅在于接收參數(shù)的方式不同。對于call()方法而言,第一個參數(shù)是作用域沒有變化,變化的只是其余的參數(shù)都是直接傳遞給函數(shù)的。換句話說,在使用call()方法時,傳遞給函數(shù)的參數(shù)必須逐個列舉出來,如下面的例子所示:
function sum (numl, num2){
return numl+num2;
}
function callSum (numl, num2){
return sum.call(this, numl, num2);
}
alert(callSum(10,10)); //20
在使用call()方法的情況下,callSum()必須明確地傳人每一個參數(shù)。結(jié)果與使用apply()沒有什么不同。至于是使用apply()還是call(),完全取決于你采取哪種給函數(shù)傳遞參數(shù)的方式最方便。如果你打算直接傳人argrnnents對象,或者包含函數(shù)中先接收到的也是一個數(shù)組,那么使用apply()肯定更方便;否則,選擇call()可能更合適。(在不給函數(shù)傳遞參數(shù)的情況下,使用哪個方法都無所謂。)事實上,傳遞參數(shù)并非apply()和call()真正的用武之地;它們真正強大的地方是能夠擴充函數(shù)賴以運行的作用域。下面來看一個例子:
window.color="red":
var o=(color:"blue");
function sayColor(){
alert(this.color);}
sayColor(); //red
sayColor.call(this); //red
sayColor.call(window); //red
sayColor.call(o); //blue
這個例子是在前面說明this對象的示例基礎(chǔ)上修改而成的。這一次,sayColor()也是作為全局函數(shù)定義的,而且當(dāng)在全局作用域中調(diào)用它時,它確實會顯示”red”——因為對this.color的求值會轉(zhuǎn)換成對window.color的求值。而sayColor.call (this)和sayColor.call (window),則是兩種顯式地在全局作用域中調(diào)用函數(shù)的方式,結(jié)果當(dāng)然都會顯示"red"。但是,當(dāng)運行sayColor.call (o) 時,函數(shù)的執(zhí)行環(huán)境就不一樣了,因為此時函數(shù)體內(nèi)的this對象指向了o,于是結(jié)果顯示的是"blue"。
使用call()(或apply())來擴充作用域的最大好處,就是對象不需要與方法有住何耦合關(guān)系。在前面例子的第一個版本中,我們是先將sayColor()函數(shù)放到了對象o中,然后再通過。來調(diào)用它的;而在這里重寫的例子中,就不需要先前那個多余的步驟了。
每個函數(shù)繼承的toLocaleString()和toString()方法始終都返回函數(shù)的代碼。返回代碼的格式則因瀏覽器而異——有的返回的代碼與源代碼中的函數(shù)代碼一樣,而有的則返回函數(shù)代碼的內(nèi)部表示,即由解析器刪除了注釋并對某些代碼作了改動后的代碼。由于存在這些差異,我們無法根據(jù)這兩個方法返回的結(jié)果來實現(xiàn)任何重要功能;不過,這些信息在調(diào)試代碼時倒是很有用。另外一個繼承的valueOf()方法同樣也只返回函數(shù)代碼。
每個函數(shù)都有一個非標準的caller屬性,該屬性指向調(diào)用當(dāng)前函數(shù)的函數(shù)。一般是在一個函數(shù)的內(nèi)部,通過arguments.callee.caller來實現(xiàn)對調(diào)用棧的追溯。目前,IE、Firefox、Safari和Chrome都支持caller屬性,但我們只建議將該屬性用于調(diào)試目的。
南昌網(wǎng)站建設(shè)公司工程師提示,讀者一定要牢記函數(shù)的名字僅僅是一個包含指針的變量而已,因此,即是在不同的環(huán)境中執(zhí)行,全局的sayColor()函數(shù)與o.sayColor()指向的仍然是同一個函數(shù)。
希望對廣大站長或網(wǎng)站建設(shè)公司或從事企業(yè)網(wǎng)站建設(shè)的團隊有所幫助,如對此不太理解的,可以與南昌網(wǎng)站設(shè)計公司百恒網(wǎng)絡(luò)技術(shù)部聯(lián)系。我們很高與廣大站長和網(wǎng)站建設(shè)公司技術(shù)人員分享我們的技術(shù)和經(jīng)驗。