Chapter 5 引用類型
Object類型
-
創建Object實例
- new Object()
var person = new Object(); person.name = "Hello";
- 使用對象字面量表示法(向函數傳遞大量參數的首選方式)
var person = { name: "Hello", age: 29 }; //屬性名可以使用字符串,效果相同 var person = { "name": "Hello", "age": 29 };
- 使用空花括號(等價于new Object())
var person = {}; person.name = "Hello";
- 訪問對象可以使用點表示法也可以使用方括號表示法
alert(person["name"]); alert(person.name); var propertyName = "name"; alert(person[propertyName]);
- 屬性名中包含會導致語法錯誤的字符,或者屬性名使用的是關鍵字或保留字,可以使用方括號表示法。
- 通常,除非必須使用方括號表示法,否則推薦使用點表示法。
Array類型
一個數組的每一項可以保存不同的數據類型
-
創建Array實例
- var colors = new Array();
- var colors = new Array(20);
- var colors = new Array("red", "green", "blue");
- var colors = ["red", "green", "blue"];
- var names = [];
- var values = [1, 2,]; //這樣會創建不一定2或3個元素的數組。
- var opts = [ , , , , , ]; //這樣會創建不一定5或6個元素的數組。
-
數組的length屬性不是只讀的
var colors = ["red", "green", "blue"]; colors.length = 2; alert(colors[2]); //undefined
var colors = ["red", "green", "blue"]; colors.length = 4; alert(colors[3]); //undefined
-
數組元素個數變化后,其length屬性會自動更新
var colors = ["red", "green", "blue"]; colors[colors.length] = "black";
var colors = ["red", "green", "blue"]; colors[99] = "black"; alert(colors.length); //100
-
可以使用檢測數組
- values instanceof Array
-
ES5+之后,使用Array.isArray()方法也可以檢測數組
- Array.isArray(values);
-
轉換方法
- toString(): 得到一個以逗號分隔的字符串
- valueOf(): 返回數組
- alert(valueOf())會后臺調用toString()
- toLocaleString()通常返回和toString()同樣的值,但是允許分別定義toString()與toLocaleString以達到不同的輸出
var person1 = { toLocaleString: function() { return "Nikolaos"; }, toString: function() { return "Nicholas"; } }; var person2 = { toLocaleString: function() { return "Grigorios"; }, toString: function() { return "Greg"; } };
- join(): 使用不同的分隔符連接數組元素
var colors = ["red", "green", "blue"]; alert(colors.join(",")); alert(colors.join("||"));
-
棧方法
- colors.push(arg1, arg2, ...); //在colors數組末尾逐個添加元素,返回值是推入個數
- colors.pop(); //彈出數組末尾的元素,并同時將數組長度減1
-
隊列方法
- colors.shift(); //取得第一項,并同時將數組長度減1
- colors.unshift(arg1, arg2, ...); //在數組的前端添加項,返回值是推入個數
var colors = new Array(); var count = colors.unshift("red", "green"); count = colors.unshift("black"); alert(colors.pop()); // "green"
-
重排序方法
- values.reverse(); //將數組元素順序顛倒
- values.sort(); //將數組按照一定規則排序(可以接收一個比較函數,默認升序)
- 返回值是經過排序后的數組
function compare(value1, value2) { if(value1 < value2) { return -1; } else if (value1 > value2) { return 1; } else { return 0; } } var values = [0, 1, 5, 10, 15]; values.sort(compare); alert(values);
function compare(value1, value2) { return value1 - value2; }
-
操作方法
- concat()
var colors = ["red", "green", "blue"]; var colors2 = colors.concat("yellow", ["black", "brown"]); //傳入一個值元素yellow和一個包含兩個值(black, brown)的數組元素 alert(colors2); //red, green, blue, yellow, black, brown
- slice()
var colors = ["red", "green", "blue", "yellow", "purple"]; var colors2 = colors.slice(1); var colors3 = colors.slice(1, 4); alert(colors2); //green, blue, yellow, purple alert(colors3); //green, blue, yellow
- splice() 向數組的中部插入項
- 刪除:splice(0, 2)刪除數組中的前兩項
- 插入:splice(2, 0, "red", "green")從當前數組的位置2開始插入字符串"red"和"green"。
- 替換:splice(2, 1, "red", "green")刪除當前數組位置2的項,并從位置2開始插入字符串"red"和"green"。
- 始終返回一個數組,包含從原數組中刪除的項(如果沒有刪除的項,則返回空數組)。
-
位置方法
- indexOf() 從數組的開頭(位置0)開始向后查找
- lastIndexOf() 從數組的末尾開始向前查找
- 接收兩個參數:要查找的項、查找起點位置的索引(可選)
- 返回 要查找的項在數組中的位置/不存在時返回-1
-
迭代方法
- every() 對數組中的每一項運行給定函數,如果該函數對每一項都返回true,則返回true
- filter() 對數組中的每一項運行給定函數,返回該函數會返回true的項組成的數組
- forEach() 對數組中的每一項運行給定函數,無返回值
- map() 對數組中的每一項運行給定函數,返回每次函數調用的結果組成的數組
- some() 對數組中的每一項運行給定函數,如果該函數對任一項返回true,則返回true
- 傳入這些方法中的函數會接收三個參數:數組項的值、該項在數組中的位置、數組對象本身
- 以上方法都不會修改數組中的包含的值
- Example
var numbers = [1, 2, 3, 4]; var everyResult = numbers.every(function(item, index, array) { return (item > 2); }); alert(everyResult); //false
-
歸并方法
- reduce() 從數組的第一項開始,逐個遍歷到最后,并構建一個返回值
- reduceRight() 從數組的最后一項開始,向前遍歷到第一項,并構建一個返回值
- 以上方法都接收兩個參數:在每一項上調用的函數、作為歸并基礎的初始值(可選);調用函數接收4個參數:前一個值、當前值、項的索引和數組對象本身。
- Example
var values = [1, 2, 3, 4, 5]; var sum = values.reduce(function(prev, cur, index, array) { return prev + cur; }); alert(sum); //15
Date類型
- 使用UTC時間1970年1月1日0時開始經過的毫秒數來保存日期,能精確到1970.1.1之前或之后的100 000 000年。
- 初始化
- var now = new Date(); // 自動獲取當前的日期和時間
- var time = new Date(1000) // 傳入指定日期的毫秒數以初始化為指定日期
- 為了簡化這個計算過程,ES提供了兩個方法:Date.parse()和Date.UTC();
- Date.parse() 接收一個表字符串參數,然后嘗試根據這個字符串返回相應時期的毫秒數。
- Date.UTC() 接收年份、基于0的月份(0-11)、月中的哪一天(1-31)、時、分、秒、毫秒,只有年月是必須的。
- Date.UTC()的日期和時間都基于本地時區創建。
- Date.now() 返回調用該方法時的日期和時間的毫秒數
- 繼承的方法
- toLocaleString() 按照與瀏覽器設置的地區相適應的格式返回日期和時間
- toString() 通常返回帶有時區信息的日期和時間,時間一般以軍用時間(0-23小時)表示
- valueOf() 不返回字符串,返回日期的毫秒表示
- 格式化方法
- toDateString() 以特定于實現的格式顯示星期、月、日、年
- toTimeString() 以特定于實現的格式顯示時、分、秒、時區
- toLocaleDateString() 以特定于地區的格式顯示星期、月、日、年
- toLocaleTimeString() 以特定于實現的格式顯示時、分、秒
- toUTCString() 以特定于實現的格式顯示完整的UTC日期
- 日期/時間組件方法
- 查閱手冊
RegExp類型
通過RegExp類型來支持正則表達式
-
字面量形式創建正則表達式:var expression = / pattern / flags;
- pattern 模式部分:可以是任何簡單或復雜的正則表達式,可以包含字符串、限定符、分組、向前查找以及反向引用。每個正則表達式都可以帶有一個或多個標志(flags),用以表明正則表達式的行為。
- flags 標志:
- g: 表示全局模式,即模式將被應用于所有字符串,而非在發現第一個匹配項時立即停止。
- i: 表示不區分大小寫模式,即在確定匹配項時忽略模式與字符串的大小寫。
- m: 表示多行模式,即在到達一行文本末尾時還會繼續查找下一行中是否存在與模式匹配的項。
- Examples
- var pattern1 = /at/g; 匹配字符串中所有的"at"實例
- var pattern2 = /[bc]at/i; 匹配第一個"bat"或"cat",不區分大小寫
- var pattern3 = /.at/gi; 匹配所有以"at"結尾的3個字符的組合,不區分大小寫
- 模式中使用的所有元字符必須轉義。包括:( [ { \ ^ & | ? * + . ] )
- var pattern4 = /[bc]at/i; 匹配第一個"[bc]at",不區分大小寫
- var pattern5 = /.at/gi; 匹配所有".at",不區分大小寫
-
使用RegExp構造函數創建正則表達式
-
接收兩個參數:要匹配的字符串模式、標志字符串(可選)
- var pattern1 = /[bc]at/i;
- var pattern2 = new RegExp("bc[at]", "i");
不能把正則表達式的字面量直接傳給RegExp構造函數。
-
需要雙重轉義
字面量模式 等價的字符串 /[bc]at/ "\[bc\]at" /.at/ "\.at" /name/age/ "name\/age" /\d.\d{1,2}/ "\d.\d{1,2}" /\w\hello\123/ "\w\\hello\\123" Example
var re = null; for(i = 0; i < 10; i++) { re = /cat/g; // 即便是循環也只創建一次RegExp實例,所以只有第一次調用test()的時候會成功,這是因為第一次調用test()時找到了"cat",但第二次調用是從索引為3的字符(上一次匹配的末尾)開始的。 re.test("catastrophe"); } for(i = 0; i < 10; i++) { re = new RegExp("cat", "g"); // 每一次迭代都會創建新的RegExp實例,所以每次循環都會創建一個新的正則表達式。 re.test("catastrophe"); }
-
-
RegExp實例屬性
- global: 布爾值,表示是否設置了g標志。
- ignoreCase: 布爾值,表示是否設置了i標志。
- lastIndex: 整數,表示開始搜索下一個匹配項的字符位置,從0算起。
- multiline: 布爾值,表示是否設置了m標志。
- source: 正則表達式的字符串表示,按照字面量形式而非傳入構造函數中的字符串模式返回。
-
RegExp實例方法
-
exec() 專門為捕獲組設計,接受一個參數:要應用模式的字符串;返回:包含第一個匹配項信息的數組|沒有匹配項返回null。
- 返回的數組是Array實例,但是包含兩個額外的屬性:index(表示匹配項在字符串中的位置)、input(表示應用的正則表達式的字符串)。在數組中,第一項是與整個模式匹配的字符串,其他項是與模式中捕獲組普配的字符串(如果沒有捕獲組,則該數組只包含一項)。
- Example
var text = "mom and dad and baby"; var pattern = /mom( and dad( and baby)?)?/gi; var matches = pattern.exec(text); alert(matches.index); // 0; alert(matches.input); // "mom and dad and baby" alert(matches[0]); // "mom and dad and baby" alert(matches[1]); // " and dad and baby" alert(matches[2]); // " and baby"
- 對于exec()方法而言,即使在模式中設置了全局標志(g),它每次也只會返回一個匹配項。在不設全局標志的情況下,在同一個字符串上多次調用exec()將始終返回第一個匹配項的信息;而設置全局標志后,每次調用exec()則會在字符串中繼續查找新的匹配項。(IE除外)
test() 接受一個字符串參數,在模式與該參數匹配的情況下返回true,否則返回false。
toString()和toLocaleString() 返回正則表達式的字面量。
-
-
構造函數屬性
- 查閱手冊
-
局限性 (JS不支持的高級正則表達式)
- 匹配字符串開始和結尾的\A和\Z錨。
- 向后查找
- 并集和交集類
- 原子組
- Unicode支持(單個字符除外)
- 命名的捕獲組
- s(單行)標志和x(無間隔)標志匹配模式
- 條件匹配
- 正則表達式注釋
Function類型
每個函數都是Function類型的實例,并且與其他引用類型一樣具有屬性和方法。
-
定義
function sum (num1, num2) { return num1 + num2; } var sum = function(num1, num2) { return num1 + num2; }; var sum = new Function("num1", "num2", "return num1 + num2"); //接收任意參數,但最后一個參數始終被作為函數體。不推薦。
-
沒有重載
- 使用相同名稱定義的函數,后一個會覆蓋前一個。
-
函數的聲明與函數表達式
-
解析器會率先讀取函數聲明,使其在執行任何代碼之前可用。但是函數表達式必須等到解析器執行到它所在的代碼行才能被解釋執行。
alert(sum(10, 10)); function sum (num1, num2) { return num1 + num2; } // 可以正確執行
alert(sum(10, 10)); var sum = function(num1, num2) { return num1 + num2; }; // 無法正確執行,因為函數在一個初始化語句中,而不是聲明。會導致第一行代碼出現unexpected indentifier錯誤。
-
-
作為值的函數
- 函數名本身是變量,所以可以被當做參數傳遞,但是要去掉圓括號。也可以當做返回值被傳遞出去。
-
函數內部屬性
- arguments: 有一個callee屬性,是一個指針,指向擁有這個arguments對象的函數。
function factorial(num) { if (num <= 1) { return 1; } else { return num * arguments.callee(num - 1); } }
- this: 引用函數執行的環境對象。
- caller: 保存著調用當前函數的引用,如果在全局作用域調用當前函數,則它的值為null。
-
函數的屬性和方法
-
屬性
- length: 表示函數希望接收的命名參數的個數
- prototype: 保存他們所有實例方法的真正所在。
-
方法
- apply(): 接收兩個參數:在其中運行函數的作用域、參數數組(可以是Array實例,也可以是arguments對象)
function sum(num1, num2) { return num1 + num2; } function callSum(num1, num2) { return sum.apply(this, arguments); } function callSum_1(num1, num2) { return sum.apply(this, [num1, num2]); }
- call(): 第一個參數是this沒有變化,其與參數直接傳遞給函數
function sum(num1, num2) { return num1 + num2; } function callSum(num1, num2) { return sum.call(this, num1, num2); }
- 真正作用:擴充函數賴以運行的作用域。
window.color = "red"; var o = { color: "blue"}; function sayColor() { alert(this.color); } sayColor(); sayColor().call(this); // "red" sayColor().call(window); // "red" sayColor().call(o); // "blue"
- apply和call在特定的作用域中調用函數,實際等于設置函數體內this對象的值。
- bind(): 創建一個函數的實例,其this值會被綁定到傳給bind()函數的值
window.color = "red"; var o = { color: "blue" }; function sayColor() { alert(this.color); } var objectSayColor = sayColor.bind(o); objectSayColor(); // "blue"
-
基本包裝類型
特殊的引用類型:Boolean Number String (基本包裝類型)
-
基本類型值不是對象,所以不應該有方法。為了實現與訪問對象一樣的方法,系統進行了一系列處理,對于代碼:
var s1 = "some text"; var s2 = s1.substring(2);
系統進行了如下處理:
- 創建String類型的一個實例
- 在實例上調用指定方法
- 銷毀這個實例
-
引用類型與基本包裝類型的主要區別:對象的生存期
- 使用new操作符創建的引用類型的實例,在執行流離開當前作用域之前都一直保存在內存中;自動創建的基本包裝類型的對象,則只存在于一行代碼的執行瞬間,然后被立即銷毀。
- 所以,不能在運行時為基本類型值添加屬性和方法。
- 可以顯式地調用Boolean Number String來創建基本包裝類型的對象,但是不推薦。對基本包裝類型的實例調用typeof會返回"object",而且所有基本包裝類型的對象都會被轉換為布爾值true。
-
Boolean類型
- var booleanObject = new Boolean(true);
- 在布爾表達式中使用Boolean對象會出現問題:
var falseObject = new Boolean(false); var result = falseObject && true; alert(result); // true
var falseValue = false; var result = falseValue && true; alert(result); // false
-
Number類型
- var numberObject = new Number(10);
- 可以為toString方法傳遞一個表示基數的參數,告訴他返回幾進制數值的字符串形式
var num = 10; alert(num.toString(2)); // "1010"
-
提供了一些用于將數值格式化為字符串的方法
- toFixed() 按照指定的小數位返回值的字符串表示
var num = 10; alert(num.toFixed(2)); // "10.00"
var num = 10.005; alert(num.toFixed(2)); // "10.01"
- toExponential() 返回以指定指數表示法表示的數值的字符串形式
var num = 10; alert(num.toExponential(1)); // "1.0e+1"
- toPrecision() 得到表示某個數值最合適的格式,接收一個參數,表示數值的所有數字的位數(不包括指數部分)
var num = 99; alert(num.toPrecision(1)); // "1e+2" alert(num.toPrecision(2)); // "99" alert(num.toPrecision(3)); //"99.0"
-
String類型
var stringObject = new String("Hello World!");
-
實例方法
- charAt()/charCodeAt() 用于訪問字符串中的特定字符,接收一個參數,即基于0的字符位置,以 單字符字符串/字符編碼 的形式,返回那個字符。
- concat() 用于將一個或多個字符串拼接起來,返回拼接得到的字符串
var stringValue = "hello "; var result = stringValue.concat("world"); alert(result); // "hello world"
- slice() substr() substring() 接收兩個參數:指定字符串開始的位置、(可選)表示字符串到哪里結束/要返回的字符個數
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" -3 會被轉換成 8 (-3 + 字符串長度11 = 8) 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);可選參數,表示從哪個位置開始搜索。
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 (IMPORTANT)
- trim() 創建一個字符串副本,刪除前置及后綴的所有空格,然后返回結果。
- toLowerCase() toLocaleLowerCase() toUpperCase() toLocaleUpperCase() 帶Locale的會進行地區優化
- 字符串模式匹配(基于String) match() search()(返回字符串中第一個匹配的索引/沒找到返回-1)
var text = "cat, bat, sat, fat"; var pattern = /.at/; var matches = text.match(pattern); // 等同于 var matches = pattern.exec(text); 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
- replace() 字符串替換 第一個參數是一個RegExp對象或者一個字符串,第二個參數是一個字符串或者一個函數(參數:模式的匹配項、模式匹配項在字符串中的位置、原始字符串),為了實現插入的效果,ES提供了一些特殊字符序列(查閱手冊)
var text = "cat, bat, sat, fat"; var result = text.replace("at", "ond"); // 只替換找到的第一個 var result = text.replace(/at/g, "ond"); // 按照正則規則,替換全部
function htmlEscape(text) { return text.replace(/[<>"&]/g, function(match, pos, originalText) { switch(match) { case "<" return "\<"; case ">" return "\>"; case "&" return "\&"; case "\" return "\"";s } }); } alert(htmlEscape("<p class=\"greeting\">Hello World!</p>")); // <p class="greeting">Hello World!</p>
- split() 基于指定分隔符將一個字符串分割成多個子字符串,并將結果放在一個數組中。分隔符可以是一個字符串,也可以是一個RegExp對象。split()可以接受可選的第二個參數,用于指定數組的大小,以確保返回的數組不會超過既定大小。
var colorText = "red, blue, green, yellow"; var color = colorText.split(/[^\,]+/); // ["", ",", ",", ",", ""]
- localeCompare() 比較兩個字符串,并返回下列值中的一個
- 如果字符串在字母表中應該排在字符串參數之前,則返回一個負數
- 如果字符串等于字符串參數,則返回0
- 如果字符串在字母表中應該排在字符串參數之后,則返回一個正數
var stringValue = "yellow"; alert(stringValue).localeCompare("brick"); // 1
- fromCharCode() 靜態方法,接收一或多個字符編碼,然后將它們轉換成一個字符串。
alert(String.fromCharCode(104, 101, 108, 111)); // "hello"
- HTML方法 查閱手冊
單體內置對象
由ES實現提供的、不依賴于宿主環境的對象,如:Object Array String..
-
Global對象
- 不屬于任何其他對象的屬性和方法,最終都是它的屬性和方法。
- URI編碼方法:使用encodeURI()和encodeURIComponent()方法可以對URI進行編碼,以便發送給瀏覽器。encodeURI()不會對本身屬于URI的特殊字符編碼,而encodeURIComponent()會對它發現的任何非標準字符進行編碼。
- URI解碼方法:decodeURI()和decodeURIComponent()
- eval()方法 完整的ES解析器,接收一個參數:要執行的ES字符串。
- eval("alert('hi')"); // 等價于 alert("hi");
- 在嚴格模式下,在外部訪問不到eval()中創建的任何變量或者函數。
- 屬性 查閱手冊
- window對象:Global對象作為window對象的一部分加以實現;因此,在全局作用域中聲明的所有變量和函數,都成為了window對象的屬性。
- 取得global對象:
var global = function() { return this; }();
-
Math對象
- 為保存數學公式和信息提供
- Math.random() 返回一個 0 - 1 的隨機數
- 查閱手冊