DIV CSS 佈局教程網

 DIV+CSS佈局教程網 >> 網頁腳本 >> JavaScript入門知識 >> 關於JavaScript >> JS函數類型知識系統
JS函數類型知識系統
編輯:關於JavaScript     
Function類型

ECMAScript中的函數實際上也是對象。每個函數都是Function類型的實例,並且與其它引用類型一樣也具有屬性和方法。所以,函數名稱實際上也是一個指向函數對象的指針。

這也就不難理解函數的另一種定義方法,實際就是在聲明一個變量:

var sum = function(num1, num2) {
return num1 + num2;
}
實際上,函數也能使用構造方法來定義,不過這種方法是不推薦使用的:

// 最後一個參數會被當成函數體
var sum = new Function("num1", "num2", "return num1 + num2");
沒有重載(深入理解)

將函數名想象為指針,也就可以理解為什麼ECMAScript當中沒有函數重載的概念。

function addSomeNumber(num) { return num + 100; }
function addSomeNumber(num) { return num + 200; }
var result = addSomeNumber(100); //

// --> 等價於 <--

var addSomeNumber = function(num) { return num + 100; }
addSomeNumber = function(num) { return num + 200; }
var result = addSomeNumber(100); // 300
可以看到,當聲明兩個同名函數時,實際上是第一個函數的變量被後面的所覆蓋了,也就無法構成重載。

函數聲明與函數表達式

在解析器向執行環境加載數據時,對待函數聲明和函數表達式是有區別的。解析器會率先讀取函數聲明,並使其可以在執行任何代碼之前可用,而對於函數表達式,則必須等到解析器執行到它所在的代碼行,才會真正被執行。

// 運行正確
alert(sum(10,10));
function sum(num1, num2){
return num1 + num2;
}

// 運行出錯
alert(sum(10,10));
var sum = function(num1, num2){
return num1 + num2;
};
由於第一段代碼使用了函數聲明,所以解析器會在運行代碼之前將其添加到執行環境中,所以可以正確運行。而第二段代碼因為是函數表達式,所以在執行第一句的時候,實際上sum函數還未被定義,導致運行出錯。

作為值的函數

因為ECMAScript當中的函數名本身就是變量,所以函數也可以被當成參數來使用,也可以作為返回值從一個函數中返回。

函數內部屬性

在函數的內部,有兩個特殊的屬性:arguments和this,這兩個屬性本身也都是引用類型。

arguments除了保存函數參數的作用,還有一個callee的屬性,該屬性是一個指針,指向擁有這個arguments對象的函數。

function factorial(num){
if (num <=1) {
return 1;
} else {
return num * factorial(num-1)
}
}
// <-- 等價於 -->
function factorial(num){
if (num <=1) {
return 1;
} else {
return num * arguments.callee(num-1)
}
}
this引用的是執行該函數的環境對象。

window.color = "red";
var o = { color: "blue" };

function sayColor(){
alert(this.color);
}

sayColor(); //"red"

o.sayColor = sayColor;
o.sayColor(); //"blue"
當在全局作用域中調用函數時,this引用的是全局對象window。而使用對象調用時,則this指向的是該對象本身。

關於this以後還會進行詳細的討論。

ECMAScript 5中還定義了另一個函數屬性的對象:caller,這個屬性保存了調用當前函數的函數的引用,如果是在全局使用域內,則它的值為null。

函數屬性和方法

因為函數也是對象,所以函數也有屬性和方法。每個函數都有兩個屬性:length和prototype。

length表示函數希望接收的命名參數的個數。

function sayName(name){
alert(name);
}

function sum(num1, num2){
return num1 + num2;
}

function sayHi(){
alert("hi");
}

alert(sayName.length); //1
alert(sum.length); //2
alert(sayHi.length); //0
prototype是ECMAScript中面向對象一個十分重要的屬性,關於這個屬性之後會更加詳細地討論。

除了上面兩個屬性,每個函數還有兩個非繼承而來的方法:apply()和call(),使用這兩個方法可以設置函數內this對象的值。

apply()方法接收兩個參數,一個是在其中運行函數的使用域,別一個是參數數組,可以是Array的實例,也可以是arguments對象。如:

function sum(num1, num2){
return num1 + num2;
}

function callSum1(num1, num2){
return sum.apply(this, arguments); // 傳入 arguments 對象
}

function callSum2(num1, num2){
return sum.apply(this, [num1, num2]); // 傳入數組
}

alert(callSum1(10,10)); //20
alert(callSum2(10,10)); //20
call()方法與apply()方法類似,區別只在於第二個參數不同,對於call()方法,所以參數都是直接指定,而不是傳遞數組。

apply()和call()方法真正強大的地方在於他們能夠擴充函數運行的作用域。

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
ECMAScript 5還定義了一個bind()方法,這個方法會創建一個函數的實例,其this值會被綁定到傳給bind()函數的值。

window.color = "red";
var o = { color: "blue" };
function sayColor(){
alert(this.color);
}

var objectSayColor = sayColor.bind(o);
objectSayColor(); //blue
而對於toString()、toLocaleString()和valueOf()方法,都會返回函數的代碼。

基本包裝類型

我們之前說過,只有引用類型的數據才能添加屬性,但是我們卻經常對字符串調用各種方法。這是怎麼回事呢?實際上,每當我們讀取一個基本類型值的時候,後台就會創建一個對應的基本包裝類型的對象,從而我們能夠調用一些方法來操作這些數據。

基本包裝類型只存在於一行代碼的執行瞬間,然後立即被銷毀。這也就解釋了為什麼我們不能為基本類型添加屬性和方法,因為對基本包裝類型添加的屬性,在下一行代碼執行的時候就被銷毀了。

我們應該避免顯式地創建基本包裝類型對象。

Boolean類型

Boolean類型是與布爾值對應的引用類型。Boolean類型的實例重寫了valueOf()方法,返回基本類型值的true或false。重寫了toString()方法,返回字符串true和false。

Number類型

Number是與數字值對應的引用類型。Number的valueOf()方法也會返回基本類型的數值,而toString()和toLocaleString()方法會返回數值對應的字符串。

Number類型還提供了一些用於數值格式化為字符串的方法。
toFixed()方法會按照指定的小數返回數值的字符串表示:

var num = 10;
alert(num.toFixed(2)); //"10.00"
toExponential()方法會返回以指數表示法表示的數值的字符串形式。

var num = 10;
alert(num.toExponential(1)); //"1.0e+1"
對於一個數值來說,toPrecision()方法可能會返回固定大小(fixed)格式,也可能返回指數格式(exponential),具體看哪種格式最合適。

var num = 99;
alert(num.toPrecision(1)); //"1e+2"
alert(num.toPrecision(2)); //"99"
alert(num.toPrecision(3)); //"99.0"
String類型

String類型是字符串的對象包裝類型。對於String類型的對象,三個繼承的方法都直接返回對象所表示的基本字符串值。String類型每個實例都有一個length屬性,表示字符串中的字符個數。要注意的是,即使字符串中包含雙字節字符,每個字符也仍然算一個字符。

String類型提供了很多方法,以提供字符串的操作和解析。

字符方法

charAt()和charCodeAt()用於訪問字符串中的特定字符。這兩個方法都接收一個參數,即基於0的字符位置。charAt()以字符形式返回給定位置的字符,而charCodeAt()會以字符編碼的形式返回。

var stringValue = "hello world";

alert(stringValue.charAt(1)); //"e"
alert(stringValue.charCodeAt(1)); // 輸出"101"
在ECMAScript 5當中,還可以使用方括號加數字索引來訪問字符串,與數組的取值方法類似。

字符串操作方法

concat()方法用於將一或多個字符串拼接起來,返回拼接得到的新字符串。

var stringValue = "hello ";
var result = stringValue.concat("world", "!");

alert(result); //"hello world!"
alert(stringValue); //"hello"
實際上,在大多數情況下,字符串拼接使用更多的還是加號操作符(+)。

ECMAScript還提供了三個用於獲取子字符串的方法:slice()、substr()和substring()。這三個方法可以接受一個或兩個參數,第一個參數為指定開始位置,對於slice()和substring(),第二個參數是指定子字符串的結束位置,而substr()的第二個參數則是指定字符的個數。

var stringValue = "hello world";
alert(stringValue.slice(3)); //"lo world"
alert(stringValue.substring(3)); //"lo world"
alert(stringValue.substr(3)); //"lo world"
alert(stringValue.slice(3, 7)); //"lo w"
alert(stringValue.substring(3,7)); //"lo w"
alert(stringValue.substr(3, 7)); //"lo worl"
在傳遞參數為負值的情況下,slice() 方法會將傳入的負值與字符串的長度相加, substr() 方法將負的第一個參數加上字符串的長度,而將負的第二個參數轉換為 0。最後, substring() 方法會把所有負值參數都轉換為 0。

var stringValue = "hello world";
alert(stringValue.slice(-3)); //"rld"
alert(stringValue.substring(-3)); //"hello world"
alert(stringValue.substr(-3)); //"rld"
alert(stringValue.slice(3, -4)); //"lo w"
alert(stringValue.substring(3, -4)); //"hel"
alert(stringValue.substr(3, -4)); //"" (空字符串)
字符串位置方法

indexOf()和lastIndexOf()可以用於從字符串中查找子字符串,並返回子字符串的位置(如果沒有找到,則返回-1)。兩個方法區別只在於搜索的起始位置。並且兩個方法都可以接受第二個參數,用於指定從哪個位置可以搜索。

trim()方法

ECMAScript 5為所有字符串字義了trim()方法。這個方法會創建一個字符串副本,刪除前置和後綴的所有空格,然後返回結果。

var stringValue = " hello world ";
var trimmedStringValue = stringValue.trim();
alert(stringValue); //" hello world "
alert(trimmedStringValue); //"hello world"
字符串大小寫轉換方法

toLowerCase()、toLocalceLowerCase()、toUpperCase()和toLocaleUpperCase()用於轉換字符串的大小寫。

字符串模式匹配方法

String類型定義了幾個用於在字符串中匹配模式的方法。

match()與RegExp的exec()方法本質上是一樣的。match()方法接收一個參數,要麼是正則字面量,或一個RegExp對象。

var text = "cat, bat, sat, fat";
var pattern = /.at/;

//與 pattern.exec(text)相同
var matches = text.match(pattern);
alert(matches.index); //0
alert(matches[0]); //"cat"
alert(pattern.lastIndex); //0
search()方法用於在字符串中查找符合特定模式的子字符串,並返回子字符串的位置,它接收的參數與match()一樣。

var text = "cat, bat, sat, fat";
var pos = text.search(/at/);
alert(pos); //1
String類型還提供了一個用於替換子字符串。這個方法可以接收兩個參數:第一個參數可以是一個RegExp對象或者一個字符串(不會被轉換為正則表達式),第二個參數可以是一個字符串或者一個函數。如果第一個參數是字符串,則只會替換第一個匹配的子字符串。

var text = "cat, bat, sat, fat";
var result = text.replace("at", "ond");
alert(result); //"cond, bat, sat, fat"

result = text.replace(/at/g, "ond");
alert(result); //"cond, bond, sond, fond"
第二個參數如果指定一個函數,傳遞給函數的參數依次是模式的匹配項、各個捕獲組的匹配項、匹配項的位置和原始字符串。

最後一個與模式匹配有關的方法是split(),這個方法可以基本指定的分隔符將一個字符串分割成多個子字符串,並將結果放在一個數組中。分隔符可以是一個字符串(不會被轉化為正則表達式),也可以是一個RegExp對象。這個方法也可以接收第二個參數,用於指定數組的大小。

var colorText = "red,blue,green,yellow";
var colors1 = colorText.split(","); //["red", "blue", "green", "yellow"]
var colors2 = colorText.split(",", 2); //["red", "blue"]
var colors3 = colorText.split(/[^\,]+/); //["", ",", ",", ",", ""]
localeCompare()方法

這個方法比較兩個字符串,根據字符編碼進行比較返回正數、負數或者0。

fromCharCode()方法

String構造函數本身還有一個靜態方法:fromCharCode(),這個方法接收一個或多個字符編碼,然後將它們轉換成一個字符串。

alert(String.fromCharCode(104, 101, 108, 108, 111)); //"hello"
單體內置對象

除了上面介紹的內置對象,ECMA-262還定義了兩個單體內置對象:Global和Math。

Global對象

所以在全局作用域中定義的屬性和函數,都是Global對象的屬性。在web浏覽器當中,這個對象被當作window對象的一部分來實現。Global對象還包含其他一些方法:

URI編碼方法

encodeURI()和encodeURIComponent()方法可以對URI進行編碼,它們會以UTF-8編碼替換掉無效的字符。其中,encodeURI()用於整個URI,而encodeURIComponent()只用於URI中某一段進行編碼。與其對應的兩個方法是decodeURI()和decodeURIComponent()。

eval()方法

eval()方法可以將傳入的字符串當作ECMAScript語句來執行。通過eval()執行的代碼被認為是包含該次調用的執行環境的一部分,因為被執行的代碼具有與該執行環境相同的作用域鏈。

eval("function sayHi() { alert('hi'); }");
sayHi();
eval("var msg = 'hello world'; ");
alert(msg); //"hello world"
Math對象

ECMAScript對保存數學公式和信息提供了一個公共位置,即Math對象。

Math對象的屬性

Math對象包含的屬性大都是數學中可能用到的特殊值:

屬性 說明
Math.E 自然對數的底數,即常量 e 的值
Math.LN10 10的自然對數
Math.LN2 2的自然對數
Math.LOG2E 以2為底 e 的對數
Math.LOG10E 以10為底 e 的對數
Math.PI π的值
Math.SQRT1_2 1/2的平方根(即2的平方根的倒數)
Math.SQRT2 2的平方根
min()和max()方法

這兩個方法可以接收任意多個數值參數,並返回所有值的最大值或最小值。

var max = Math.max(3, 54, 32, 16);
alert(max); //54

var min = Math.min(3, 54, 32, 16);
alert(min); //3
捨入方法

Math.ceil()向上取整,Math.floor()向下取整,Math.round()執行四捨五入方法。

alert(Math.ceil(25.9)); //26
alert(Math.ceil(25.5)); //26
alert(Math.ceil(25.1)); //26

alert(Math.round(25.9)); //26
alert(Math.round(25.5)); //26
alert(Math.round(25.1)); //25

alert(Math.floor(25.9)); //25
alert(Math.floor(25.5)); //25
alert(Math.floor(25.1)); //25
random()方法

Math.random()方法返回大於等於0小於1的一個隨機數。可以利用這個方法從某個整數范圍內隨機選擇一個值。

值 = Math.floor(Math.random() * 可能值的總數 + 第一個可能的值)
// 通用函數
function selectFrom(lowerValue, upperValue) {
var choices = upperValue - lowerValue + 1;
return Math.floor(Math.random() * choices + lowerValue);
}
其他方法

Math對象中還包含了其他一些與計算相關的方法,在此就不詳細記錄,遇到的時候再查閱資料就可以了。
XML學習教程| jQuery入門知識| AJAX入門| Dreamweaver教程| Fireworks入門知識| SEO技巧| SEO優化集錦|
Copyright © DIV+CSS佈局教程網 All Rights Reserved