1. 程式人生 > >《Javascript 高階程式設計(第三版)》筆記0x7 引用型別(2)

《Javascript 高階程式設計(第三版)》筆記0x7 引用型別(2)

目錄

 

Function 型別

     沒有過載

    函式宣告與函式表示式

     作為值的函式

      將一個函式作為另一個函式的結果返回

       從一個函式中返回另一個函式

    函式內部屬性

      callee 屬性

       this

      caller 

    函式屬性和方法

      屬性:length 和 prototype

      方法:apply()和 call()

       bind()

基本包裝型別

     Boolean型別

     Number型別

    String型別

      字元方法

      字串操作方法

      字串位置方法

      trim()方法

      字串大小寫轉換方法

      字串的模式匹配方法

       localeCompare()方法

      fromCharCode()方法

      HTML 方法

單體內建物件

    Global物件

        URI 編碼方法

       eval()方法

      Global 物件的屬性

       window 物件

    Math物件

      Math 物件的屬性

      min()和 max()方法 

      舍入方法

      random()方法

      其他方法


Function 型別

      函式實際上是物件。每個函式都是 Function 型別的例項,而且都與其他引用型別一樣具有屬性和方法。由於函式是物件,因此函式名實際上也是一個指向函式物件的指標,不會與某個函式繫結。

function sum (num1, num2) {
    return num1 + num2;
}
//這與下面使用函式表示式定義函式的方式幾乎相差無幾。
var sum = function(num1, num2){//在使用函式表示式定義函式時,沒有必要使用函式名——通過變數 sum 即可以引用函式
    return num1 + num2;
};

//使用 Function 建構函式
var sum = new Function("num1", "num2", "return num1 + num2"); // 不推薦

         由於函式名僅僅是指向函式的指標,因此函式名與包含物件指標的其他變數沒有什麼不同。換句話說,一個函式可能會有多個名字.

function sum(num1, num2){
    return num1 + num2;
}
alert(sum(10,10)); //20
var anotherSum = sum;
alert(anotherSum(10,10)); //20
sum = null;
alert(anotherSum(10,10)); //20
//注意即使將 sum 設定為 null,讓它與函式“斷絕關係”,但仍然可以正常呼叫anotherSum()。

     沒有過載

//函式名是指標,那後面的函式名自然會覆蓋前面
function addSomeNumber(num){
    return num + 100;
}
function addSomeNumber(num) {
    return num + 200;
}
var result = addSomeNumber(100); //300

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

    函式宣告與函式表示式

        解析器會率先讀取函式宣告,並使其在執行任何程式碼之前可用(可以訪問);至於函式表示式,則必須等到解析器執行到它所在的程式碼行,才會真正被解釋執行。

     作為值的函式

      將一個函式作為另一個函式的結果返回

function callSomeFunction(someFunction, someArgument){
        return someFunction(someArgument);
}

function add10(num){
    return num + 10;
}
var result1 = callSomeFunction(add10, 10);
alert(result1); //20
function getGreeting(name){
    return "Hello, " + name;
}
var result2 = callSomeFunction(getGreeting, "Nicholas");
alert(result2); //"Hello, Nicholas"

       從一個函式中返回另一個函式

function createComparisonFunction(propertyName) {
	return function(object1, object2){
		var value1 = object1[propertyName];
		var value2 = object2[propertyName];
		if (value1 < value2){
			return -1;
		} else if (value1 > value2){
			return 1;
		} else {
			return 0;
		}
	};
}

var data = [{name: "Zachary", age: 28}, {name: "Nicholas", age: 29}];
data.sort(createComparisonFunction("name"));
alert(data[0].name); //Nicholas
data.sort(createComparisonFunction("age"));
alert(data[0].name); //Zachary

    函式內部屬性

        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

        引用的是函資料以執行的環境物件

//當在網頁的全域性作用域中呼叫函式時,this 物件引用的就是 window
window.color = "red";
var o = { color: "blue" };
function sayColor(){
    alert(this.color);
}
sayColor(); //"red"
o.sayColor = sayColor;
o.sayColor(); //"blue"

        函式的名字僅僅是一個包含指標的變數而已。因此,即使是在不同的環境中執行,全域性的 sayColor()函式與 o.sayColor()指向的仍然是同一個函式。

      caller 

        儲存著呼叫當前函式的函式的引用,如果是在全域性作用域中呼叫當前函式,它的值為 null。

function outer(){
    inner();
}
function inner(){
    alert(arguments.callee.caller);
}
outer();

    函式屬性和方法

      屬性: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

        對於ECMAScript 中的引用型別而言, prototype 是儲存它們所有例項方法的真正所在。換句話說,諸如toString()和 valueOf()等方法實際上都儲存在 prototype 名下,只不過是通過各自物件的例項訪問罷了。

      方法:apply()和 call()

/*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()方法而言,第一個引數是 this 值沒有變化,變化的是其餘引數都直接傳遞給函式。*/
function sum(num1, num2){
    return num1 + num2;
}
function callSum(num1, num2){
    return sum.call(this, num1, num2);
}
alert(callSum(10,10)); //20

        傳遞引數並非 apply()和 call()真正的用武之地;它們真正強大的地方是能夠擴充函式賴以執行的作用域。使用 call()(或 apply())來擴充作用域的最大好處,就是物件不需要與方法有任何耦合關係。

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

       bind()

         這個方法會建立一個函式的例項,其 this 值會被繫結到傳給 bind()函式的值。

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

基本包裝型別

        為了便於操作基本型別值, ECMAScript 還提供了 3 個特殊的引用型別: Boolean、 Number 和String。

var s1 = "some text";
var s2 = s1.substring(2);
//相當於
var s1 = new String("some text");
var s2 = s1.substring(2);
s1 = null;

        引用型別與基本包裝型別的主要區別就是物件的生存期。使用 new 操作符建立的引用型別的例項,在執行流離開當前作用域之前都一直儲存在記憶體中。而自動建立的基本包裝型別的物件,則只存在於一行程式碼的執行瞬間,然後立即被銷燬。這意味著我們不能在執行時為基本型別值新增屬性和方法。

        Object 建構函式也會像工廠方法一樣,根據傳入值的型別返回相應基本包裝型別的例項。 

var obj = new Object("some text");
alert(obj instanceof String); //true

     Boolean型別

var booleanObject = new Boolean(true);

var falseObject = new Boolean(false);
var result = falseObject && true;
alert(result); //true

var falseValue = false;
result = falseValue && true;
alert(result); //false

        首先, typeof 操作符對基本型別返回"boolean",而對引用型別返回"object"。其次,由於 Boolean 物件是 Boolean 型別的例項,所以使用 instanceof操作符測試 Boolean 物件會返回 true,而測試基本型別的布林值則返回 false。

alert(typeof falseObject); //object
alert(typeof falseValue); //boolean
alert(falseObject instanceof Boolean); //true
alert(falseValue instanceof Boolean); //false

     Number型別

var num = 10;
alert(num.toString()); //"10"
alert(num.toString(2)); //"1010"
alert(num.toString(8)); //"12"
alert(num.toString(10)); //"10"
alert(num.toString(16)); //"a"

alert(num.toFixed(2)); //"10.00"

alert(num.toExponential(1)); //"1.0e+1"

var num = 10.005;
alert(num.toFixed(2)); //"10.01"

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

var numberObject = new Number(10);
var numberValue = 10;
alert(typeof numberObject); //"object"
alert(typeof numberValue); //"number"
alert(numberObject instanceof Number); //true
alert(numberValue instanceof Number); //false

    String型別

var stringObject = new String("hello world");

var stringValue = "hello world";
alert(stringValue.length); //"11"

      字元方法

var stringValue = "hello world";
alert(stringValue.charAt(1)); //"e"

alert(stringValue.charCodeAt(1)); //輸出"101"

alert(stringValue[1]); //"e"

      字串操作方法

var stringValue = "hello ";
var result = stringValue.concat("world");
alert(result); //"hello world"
alert(stringValue); //"hello"

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

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"

var stringValue = "hello world";
alert(stringValue.slice(-3)); //"rld",slice()方法會將傳入的負值與字串的長度相加
alert(stringValue.substring(-3)); //"hello world"
alert(stringValue.substr(-3)); //"rld"
alert(stringValue.slice(3, -4)); //"lo w"
alert(stringValue.substring(3, -4)); //"hel",ubstring()方法會把所有負值引數都轉換為 0。
alert(stringValue.substr(3, -4)); //""(空字串),substr()方法將負的第一個引數加上字串的長度,而將負的第二個引數轉換為 0

      字串位置方法

var stringValue = "hello world";
alert(stringValue.indexOf("o")); //4
alert(stringValue.lastIndexOf("o")); //7

var stringValue = "hello world";//第二個引數,表示從字串中的哪個位置開始搜尋。
alert(stringValue.indexOf("o", 6)); //7
alert(stringValue.lastIndexOf("o", 6)); //4

      trim()方法

var stringValue = " hello world ";
var trimmedStringValue = stringValue.trim();
alert(stringValue); //" hello world "
alert(trimmedStringValue); //"hello world"

      字串大小寫轉換方法

var stringValue = "hello world";
alert(stringValue.toLocaleUpperCase()); //"HELLO WORLD"
alert(stringValue.toUpperCase()); //"HELLO WORLD"
alert(stringValue.toLocaleLowerCase()); //"hello world"
alert(stringValue.toLowerCase()); //"hello world"

      字串的模式匹配方法

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

var text = "cat, bat, sat, fat";
var pos = text.search(/at/);
alert(pos); //1

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"

var text = "cat, bat, sat, fat";
result = text.replace(/(.at)/g, "word ($1)");
alert(result); //word (cat), word (bat), word (sat), word (fat)

       localeCompare()方法

var stringValue = "yellow";
alert(stringValue.localeCompare("brick")); //1
alert(stringValue.localeCompare("yellow")); //0
alert(stringValue.localeCompare("zoo")); //-1

      fromCharCode()方法

alert(String.fromCharCode(104, 101, 108, 108, 111)); //"hello"

      HTML 方法

使用 JavaScript 動態格式化 HTML

單體內建物件

        “由 ECMAScript 實現提供的、不依賴於宿主環境的物件,這些物件在 ECMAScript 程式執行之前就已經存在了。” 

    Global物件

        ECMAScript 中的 Global 物件在某種意義上是作為一個終極的“兜底兒物件”來定義的。換句話說,不屬於任何其他物件的屬性和方法,最終都是它的屬性和方法。事實上,沒有全域性變數或全域性函式;所有在全域性作用域中定義的屬性和函式,都是 Global 物件的屬性。 

        URI 編碼方法

        Global 物件的 encodeURI()和 encodeURIComponent()方法可以對 URI(Uniform Resource Identifiers,通用資源識別符號)進行編碼,以便傳送給瀏覽器。有效的 URI 中不能包含某些字元。 

         encodeURI()主要用於整個 URI(例如, http://www.wrox.com/illegal value.htm),而 encodeURIComponent()主要用於對 URI 中的某一段(例如前面 URI 中的 illegal value.htm)進行編碼。它們的主要區別在於, encodeURI()不會對本身屬於 URI 的特殊字元進行編碼,例如冒號、正斜槓、問號和井字號;而 encodeURIComponent()則會對它發現的任何非標準字元進行編碼。

var uri = "http://www.wrox.com/illegal value.htm#start";

alert(encodeURI(uri));//"http://www.wrox.com/illegal%20value.htm#start"
alert(encodeURIComponent(uri));//"http%3A%2F%2Fwww.wrox.com%2Fillegal%20value.htm%23start"

var uri = "http%3A%2F%2Fwww.wrox.com%2Fillegal%20value.htm%23start";

alert(decodeURI(uri));//http%3A%2F%2Fwww.wrox.com%2Fillegal value.htm%23start
alert(decodeURIComponent(uri));//http://www.wrox.com/illegal value.htm#start

       eval()方法

        eval()方法就像是一個完整的 ECMAScript 解析器,它只接受一個引數,即要執行的 ECMAScript (或 JavaScript)字串。

var msg = "hello world";
eval("alert(msg)"); //"hello world"

eval("var msg = 'hello world'; ");
alert(msg); //"hello world"

         能夠解釋程式碼字串的能力非常強大,但也非常危險。因此在使用 eval()時必須極為謹慎,特別是在用它執行使用者輸入資料的情況下。否則,可能會有惡意使用者輸入威脅你的站點或應用程式安全的程式碼(即所謂的程式碼注入)。

      Global 物件的屬性

       window 物件

        ECMAScript 雖然沒有指出如何直接訪問 Global 物件,但 Web 瀏覽器都是將這個全域性物件作為window 物件的一部分加以實現的。因此,在全域性作用域中宣告的所有變數和函式,就都成為了 window物件的屬性。

var color = "red";
function sayColor(){
    alert(window.color);
}
window.sayColor(); //"red",全域性變數是 window 物件的屬性

//另一種取得 Global 物件的方法是使用以下程式碼:
var global = function(){
    return this;
}();

    Math物件

      Math 物件的屬性

      min()和 max()方法 

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

var values = [1, 2, 3, 4, 5, 6, 7, 8];
var max = Math.max.apply(Math, values);

      舍入方法

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()方法

var num = Math.floor(Math.random() * 10 + 1);//選擇一個 1到 10 之間的數值

var num = Math.floor(Math.random() * 9 + 2);//選擇一個介於 2 到 10 之間的值

      其他方法