【javascript進階程式設計】讀書摘錄2 第五章、參考型別,javascript第五章
第五章、參考型別
1、建立Object的方式有兩種
第一種是使用new操作符: varperson = new Object();
第二種是使用對象字面量標記法:var person = {name : ‘test’}; (注意最後一個屬性後面不要加逗號,否則在某些瀏覽器中可能會出現錯誤),在使用字面量建立對象時,屬性名稱也可以使用字串:var person = {“name”:”test”};
2、訪問對象屬性時可以使用點標記法,也可以使用方括弧標記法來訪問對象的屬性:
var person = {“name”:”test”};alert(person.name);alert(person[“name”]);
這兩種方式沒有太大區別,但是使用方括弧文法可以通過變數來訪問屬性。
1、 Array類型:
var arr1 = new Array();var arr2 = Array(1, 2, 3);var arr3 = [];
2、 棧方法:
ECMAScript提供了一種讓數組的行為類似於其他資料結構的方法,例如棧和隊列
var stack = []; for( var i = 0; i< 10; i++ ){ stack.push(i ); } console.log( stack.join("-") ); for( var i = 0; i < 5; i++ ){ console.log("pop: " + stack.pop() ); }
3、 隊列方法:
隊列方法在隊列的末尾添加項,而在隊列的前端移除項
var queue = [];for( var i = 0; i < 10; i++ ){ queue.push( i );}console.log( queue.join("-") );for( var i = 0; i < 5; i++ ){ console.log( "shift: " + queue.shift() );}
unshift的作用與shift相反,能在數組的前端添加任意多個項並返回數組的長度。
4、 數組函數
sort可以完成對數組的排序,reverse會翻轉數組項的順序。
與大多數排序函數類似,sort可以接受一個比較函數,從而實現對數組的自訂排序:
concat(): 基於原來的數組拼接新的數組:
var colors = ["red","green" ];console.log( colors.concat(["blue","yellow"]) );
slice(): 擷取數組的一部分作為新的數組:
var arr = [1, 2, 3, 4, 5];console.log( arr.slice(2, 4));
splice數組:數組中插入、刪除或者替換項:
(1)、刪除
var colors = ['r', 'g', 'b']; var removed = colors.splice(0, 2); console.log(removed);
(2)、添加
var colors = ['r', 'g', 'b'];var removed = colors.splice(1, 0, "added");console.log(colors);
(3)、替換
var colors = ['r', 'g', 'b'];var removed = colors.splice(1,1 , "redd","blue");console.log(removed);
8、Date類型
Date類型的valueOf方法根本不返回字串,而是返回日期的毫秒錶示。因而可以直接用比較操作符直接比較日期值:
var date1 = new Date(2007, 1, 1);var date2 = new Date(2007, 1, 2);console.log( date1 < date2 );
Date的組件方法,參考文檔,比較多,不細列出。比較重要的有:
getTime() : 返回表示日期的毫秒數,與valueOf一致。
setTime(): 設定日期
getFullYear(): 取得四位元的年份
getMonth(): 取得月份
getDate(): 返回月份中的天數
……
9、RegExp類型
ECMAScript通過RegExp類型來支援Regex。
varpattern = /pattern/flags
flags有三種:
g:表示全域匹配模式,模式被應用於整個字串,而不是發現第一個匹配項時停止
i:不區分大小寫匹配
m:多行模式,到達一行文本結尾時還會繼續尋找下一行的文本。
另一種建立Regex的方式是通過RegExp對象:
var pattern = newRegExp("[bc]at", "i");
傳遞給RegExp的兩個參數都是字串,不能把Regex的字面量直接傳遞給RegExp。由於RegExp建構函式的模式參數是字串,因而在某些情況下需要對字元進行雙重轉義,所有元字元都必須雙重轉義。
RegExp的執行個體都具有如下的一些屬性:
(1) global表明是否啟用了g標誌
(2) ignorecase是否啟用了i標誌
(3) lastIndex表示搜尋下一個匹配項的字元位置,從0開始
(4) multiline 是否啟用了m標誌
(5) source Regex的字串表示,按照字面量形式返回。
var pattern1 = /\[bc\]at/i;var pattern2 = newRegExp("\\[bc\\]at", "i");console.log(pattern1.global);console.log(pattern1.ignoreCase);console.log(pattern1.multiline);console.log(pattern1.lastIndex);console.log(pattern1.source);console.log(pattern2.source);
RegExp對象有兩個常見執行個體方法:exec() 和 test();
exec專為擷取的群組而設計的,exec接收一個字串參數,返回包含匹配項的數組:
test()接收一個字串參數,在參數與Regex匹配時返回true, 否則返回false
ECMAScriptRegex不支援的特性:
(1)、匹配字串開始和結束的\A和\Z錨點
(2)、向後尋找lookbehind
(3)、並集和交集類
(4)、原子組
(5)、Unicode支援(單個字元除外)
(6)、命名的擷取的群組
(7)、s和x匹配模式
(8)、條件匹配
(9)、Regex注釋
10、Function類型
每個函數都是Function函數的執行個體,而且都與其他參考型別一樣具有屬性和方法。由於函數是對象,因此函數名實際上是一個指向函數對象的指標。
由於函數名僅僅是指向函數的指標,因此函數名與包含對象指標的其他變數沒有什麼不同,一個函數可以有多個名字:
function sum(a, b){ returna + b;} var antSum = sum;console.log( antSum(1, 2) );sum = null;console.log( antSum(1, 2) );
將函數名想象成指標,也就解釋了為什麼ECMAScript中沒有函數重載的概念。
解析器在載入資料時,對於函式宣告和函數運算式並非一視同仁:解析器會率先讀取函式宣告,並使其在執行任何代碼之前可用;而對於函數運算式,則必須等到解析器執行到它所在的程式碼時才會真正被解釋執行,如下的方式在執行期會導致錯誤:
console.log( sum(1, 2) );var sum = function(a, b){ returna + b;}
由於ECMAScript中的函數名本身就是變數,所以函數也可以作為值來使用。也就是說,不僅可以像傳遞參數一樣吧一個函數傳遞給另一個函數,而且可以把一個函數作為另一個函數的結果返回。從這個意義上說,函數是ECMAScript中的一等公民。
可以從一個函數中返回函數,例如建立一個根據屬性名稱進行比較的函數(用於排序):
function createCompare( prop ){ return function( obj1, obj2 ){ var v1 = obj1[ prop ]; var v2 = obj2[ prop ]; if( v1 < v2 ){ return -1; }else if( v1 > v2 ){ return 1; }else{ return 0; } }; }
注意這裡如果使用return v1 – v2;則是錯誤的,因為對於字串而言, 字串相減返回的結果是NaN。
函數內部,有兩個特殊的屬性:this和arguments。其中arguments是一個類數組對象,其中包含了傳入函數的所有參數:
functiontest(){ console.log( arguments ); console.log(arguments.length );}test(1,2, 3, 4, 5);
雖然arguments的主要作用是儲存函數參數,但是這個對象還有一個名叫callee的屬性,該屬性是一個指標,指向擁有這個arguments對
象的函數:
function factor( num ){ if( num <= 1 ){ return 1; } return num * arguments.callee( num - 1 );}
使用arguments.callee可以保證無論函數使用什麼名字,都能正確完成遞迴(解除耦合)。
函數內部另一個特殊對象是this,this是函數在執行時所處的範圍(當前網頁的全域範圍中調用函數時,this對象引用的就是window)
函數屬性和方法:ECMAScript函數是對象,因此函數也有屬性和方法,每個函數包含兩個屬性:length和prototype,其中,length表示函數希望接收的具名引數的個數:
function sum(a, b){ return a + b;}console.log(sum.length);
prototype可以說是ECMAScript中最重要的屬性了(詳見第六章)
每個函數都包含兩個繼承而來的方法:apply和call,這兩個方法的用途是在特定的範圍中調用函數,實際上等於設定函數體內this對象的值:
function sum(a, b){ return a + b;}function callSum(a, b){ //函數是在全域範圍被調用的,因此this == window return sum.apply(this, arguments);}function callSum2(a, b){ return sum.apply( this, [a, b] );}console.log(callSum(1, 2));console.log(callSum2(2, 3));
call方法和apply方法作用相同,它們的區別在於接收參數的方式不同:
function callSum(a, b){ return sum.call(this, a, b);}console.log(callSum(1, 3));
實際上,傳遞參數並非call和apply真正的用武之地,它們真正強大的地方在於能夠擴充函數賴以啟動並執行範圍。:
var color = "red";var o = {color : "blue"};function sayColor(){ console.log(this + " this.color: " + this.color);}sayColor();sayColor.call(this);sayColor.call( o );
用call和apply來擴從範圍的最大好處,就是對象不需要與方法有任何耦合關係
11、基本封裝類型
為了便於操作基本類型值,ECMAScript還提供了3個特殊的參考型別:Boolean、Number和String.
參考型別和基本封裝類型的區別在於對象的生存期,使用New操作符建立的參考型別的執行個體,在執行流離開當前範圍之前一直都儲存在記憶體中,而自動建立的自動封裝類型的對象,則只存在於一行代碼的執行瞬間,然後立即被銷毀。這意味著不能為基本類型值添加屬性和方法:
vars = "some test";s.color= "red";console.log(s.color );//undefined
不建議顯式地建立基本封裝類型的對象。
toFixed和 toExponential,toPrecision 兩個用於格式化數值的方法。
使用typeof操作符測試基本類型數值時,始終會返回"number",而在測試Number對象時,則會返回object. Number對象是Number類型的執行個體,而基本類型的則不是。
String類型:
String類型的每個執行個體都含有一個length屬性,表示字串包含多少個字元(多位元組字元依然算一個字元):
var s = "some test好";console.log( s.length );
charAt和charCodeAt用於訪問字串中的特定字元。其中charAt返回給定位置的單個字元,而charCodeAt則返回的是指定位置的字元編碼:
vars = "hello";console.log(s.charAt(2));//lconsole.log(s.charCodeAt(2));//108
concat用於將一個或者多個字串拼接起來,返回拼接到的新字串。
slice, substr, substring: 基於子字串建立新的字串(它們都不修改原始字串的值,而只是返回一個基本類型的字串值):
string.slice(start, end);
string.substring(start, end);
string.substr(start, len);
indexOf返回子字串的位置,如果沒有找到,返回-1(向後搜尋)
lastIndexOf返回子字串最後一次出現的位置(向前搜尋)
可以通過迴圈尋找,找出所有子串在字串中的所有位置:
字串匹配:match和search
容易搞混的地方: test()和exec()是Regex的方法,RegExp.test(str), RegExp.exec(str);
而match和search是字串的操作方法,str.match(RegExp), str.search(RegExp)
replace用於替換,第一個參數可以是RegExpRegex或者字串,如果是字串,那麼只會替換第一個子字串,如果要替換所有的字串,可以提供一個Regex,而且指定全域標誌(g).第二個參數可以將Regex操作得到的值插入到結果字串中:
var text = "cat, bat, sat, fat",result = text.replace(/(.at)/g, "word($1)");console.log( result );
replace的第二個參數也可以是一個函數:在只有一個匹配項的情況下,會向這個函數傳入3個參數:模式的匹配項、模式比對項的起始位置和原始的字串:
function htmlEscape( str ){ return str.replace(/[<>"&]/g, function( match, pos, orig){ switch( match ){ case "<": return "<"; break; case ">": return ">"; break; case "&": return "&"; break; case "\"": return """; break; } });}
split用於模式分割:
var colorStr = "red, blue, green,red";console.log( colorStr.split(","));console.log( colorStr.split(",",2) );
fromCharCode接收一個或者多個字元編碼,然後將他們轉換為一個字串:
var str = String.fromCharCode( 104, 101,108, 108, 111 );console.log( str );
12、內建對象
Global對象:不屬於任何其他對象的屬性和方法,最終都是Global對象的屬性和方法。實際上,沒有全域變數或者全域函數,所有在全域範圍中定義的屬性和函數,都是Global對象的屬性。
URL編碼方法:
Global對象的encodeURI和encodeURIComponent()方法可以對URI進行編碼。
encodeURI主要用於對整個URI進行編碼,而encodeURIComponent主要用於對URI的某一段進行編碼。它們的主要區別在於,encodeURI不會對本身屬於URI的特殊字元進行編碼,例如冒號:,正斜杠/,問號?和井號#; 而encodeURIComponent則會對它發現的任何非標準的字元進行編碼:
var uri = "http://www.prox.com/illvalue#start";//http://www.prox.com/ill%20value#startconsole.log( encodeURI(uri) );//http%3A%2F%2Fwww.prox.com%2Fill%20value%23startconsole.log( encodeURIComponent(uri) );
與encodeURI和encodeURIComponent對應的兩個方法分別是decodeURI和decodeURIComponent,它們是一一對應的,decodeURI只能對使用encodeURI編碼的字元進行解碼,同樣,decodeURIComponent只能對使用encodeURIComponent編碼的字元進行解碼。
eval:
eval中可以定義函數,這個函數可以被外部調用
eval(" functionsayHi(){console.log('hi');} ");
sayHi();
window對象: ECMAScript雖然沒有指出如何直接存取Global對象,但Web瀏覽器都是將這個全域變數作為Window對象的一部分加以實現的。因此,在全域範圍中聲明的所有變數和函數,都成了window對象的屬性.
var color = "red";function sayColor( ){ console.log(window.color);}window.sayColor();
Math對象:
Math對象的屬性包括:
Math.E
Math.LN10
Math.LN2
Math.LOG2E
Math.LOG10E
Math.PI
Math.SQRT1_2
Math.SQRT2
Math對象的方法:
(1) min和max方法,用於確定一組數值中的最大和最小值。
(2) 舍入方法: Math.ceil(), Math.floor(), Math.round
(3) random()方法。返回0-1之間的隨機數,不包含0和1,套用公式:
val = Math.floor(Math.random()* 可能的值總數 + 第一個可能的值)可以實現在一個range中選擇一個值。
functionselectFrom(low, high){ var nums = high – low + 1; return Math.floor( nums * Math.random() + low );}console.log(selectFrom(2,10));
(4) abs(num), exp(num), log(num),pow(num, power)