Object
對象,即那些對象都是Object
的實例。Object
對象的原生方法分紅兩類:Object
自己的方法與Object
的實例方法。(1)Object對象自己的方法(靜態方法)javascript
所謂「自己的方法」就是直接定義在Object
對象的方法。java
Object.print = function (o) { console.log(o) };
複製代碼
上面代碼中,print
方法就是直接定義在Object
對象上。正則表達式
(2)Object的實例方法編程
所謂實例方法就是定義在Object
原型對象Object.prototype
上的方法。它能夠被Object
實例直接使用。數組
Object.prototype.print = function () {
console.log(this);
};
var obj = new Object();
obj.print() // Object
複製代碼
Object自己是一個函數,能夠看成工具方法使用,將任意值轉爲對象。這個方法經常使用於保證某個值必定是對象。bash
Object
方法的參數是一個對象,它老是返回該對象,即不用轉換。利用這一點,能夠寫一個判斷變量是否爲對象的函數。數據結構
function isObject(value) {
return value === Object(value);
}
isObject([]) // true
isObject(true) // false
複製代碼
Object.keys()方法的參數是一個對象,返回一個數組。該數組的成員都是該對象自身的全部屬性名。(可枚舉) Object.getOwnPropertyNames()返回一個數組,包含了該對象自身的全部屬性名(不可枚舉)app
(1)對象屬性模型的相關方法 Object.getOwnPropertyDescriptor():獲取某個屬性的描述對象。 Object.defineProperty():經過描述對象,定義某個屬性。 Object.defineProperties():經過描述對象,定義多個屬性。函數
(2)控制對象狀態的方法 Object.preventExtensions():防止對象擴展。 Object.isExtensible():判斷對象是否可擴展。 Object.seal():禁止對象配置。 Object.isSealed():判斷一個對象是否可配置。 Object.freeze():凍結一個對象。 Object.isFrozen():判斷一個對象是否被凍結。工具
(3)原型鏈相關方法 Object.create():該方法能夠指定原型對象和屬性,返回一個新的對象。 Object.getPrototypeOf():獲取對象的Prototype對象。
除了靜態方法,還有很多方法定義在Object.prototype
對象。它們稱爲實例方法,全部Object
的實例對象都繼承了這些方法。
Object實例對象的方法,主要有如下六個。
Object.prototype.valueOf():返回當前對象對應的值。 Object.prototype.toString():返回當前對象對應的字符串形式。 Object.prototype.toLocaleString():返回當前對象對應的本地字符串形式。 Object.prototype.hasOwnProperty():判斷某個屬性是否爲當前對象自身的屬性,仍是繼承自原型對象的屬性。 Object.prototype.isPrototypeOf():判斷當前對象是否爲另外一個對象的原型。 Object.prototype.propertyIsEnumerable():判斷某個屬性是否可枚舉。
技巧:只作一個精確的類型判斷方法
var type = function (o){
var s = Object.prototype.toString.call(o);
return s.match(/\[object (.*?)\]/)[1].toLowerCase();
};
複製代碼
延伸:判斷具體類型的方法
var type = function (o){
var s = Object.prototype.toString.call(o);
return s.match(/\[object (.*?)\]/)[1].toLowerCase();
};
['Null',
'Undefined',
'Object',
'Array',
'String',
'Number',
'Boolean',
'Function',
'RegExp'
].forEach(function (t) {
type['is' + t] = function (o) {
return type(o) === t.toLowerCase();
};
});
type.isObject({}) // true
type.isNumber(NaN) // true
type.isRegExp(/abc/) // true
複製代碼
JavaScript 提供了一個內部數據結構,用來描述對象的屬性,控制它的行爲,好比該屬性是否可寫、可遍歷等等。這個內部數據結構稱爲「屬性描述對象」(attributes object)。每一個屬性都有本身對應的屬性描述對象,保存該屬性的一些元信息。
下面是屬性描述對象的一個例子。
{
value: 123,
writable: false,
enumerable: true,
configurable: false,
get: undefined,
set: undefined
}
複製代碼
屬性描述對象提供6個元屬性。
(1)value
value
是該屬性的屬性值,默認爲undefined
。
(2)writable
writable
是一個布爾值,表示屬性值(value)是否可改變(便是否可寫),默認爲true
。
(3)enumerable
enumerable
是一個布爾值,表示該屬性是否可遍歷,默認爲true
。若是設爲false
,會使得某些操做(好比for...in
循環、Object.keys()
)跳過該屬性。
(4)configurable
configurable
是一個布爾值,表示可配置性,默認爲true
。若是設爲false
,將阻止某些操做改寫該屬性,好比沒法刪除該屬性,也不得改變該屬性的屬性描述對象(value
屬性除外)。也就是說,configurable
屬性控制了屬性描述對象的可寫性。
(5)get
get
是一個函數,表示該屬性的取值函數(getter),默認爲undefined
。
(6)set
set
是一個函數,表示該屬性的存值函數(setter),默認爲undefined
。
若是一個屬性的enumerable
爲false
,下面三個操做不會取到該屬性。
for..in
循環Object.keys
方法JSON.stringify
方法所以,enumerable
能夠用來設置「祕密」屬性。
正常寫法
var obj = Object.defineProperty({}, 'p', {
get: function () {
return 'getter';
},
set: function (value) {
console.log('setter: ' + value);
}
});
複製代碼
特殊寫法
JavaScript 還提供了存取器的另外一種寫法。
var obj = {
get p() {
return 'getter';
},
set p(value) {
console.log('setter: ' + value);
}
};
複製代碼
屬性的元對象設置都會拷貝
var extend = function (to, from) {
for (var property in from) {
if (!from.hasOwnProperty(property)) continue;
Object.defineProperty(
to,
property,
Object.getOwnPropertyDescriptor(from, property)
);
}
return to;
}
extend({}, { get a(){ return 1 } })
複製代碼
有時須要凍結對象的讀寫狀態,防止對象被改變。JavaScript 提供了三種凍結方法,最弱的一種是Object.preventExtensions
,其次是Object.seal
,最強的是Object.freeze
。
1.Object.preventExtensions
方法可使得一個對象沒法再添加新的屬性。
Object.isExtensible
方法用於檢查一個對象是否使用了Object.preventExtensions
方法。也就是說,檢查是否能夠爲一個對象添加屬性。
2.Object.seal
方法使得一個對象既沒法添加新屬性,也沒法刪除舊屬性。
Object.isSealed
方法用於檢查一個對象是否使用了Object.seal
方法。
3.Object.freeze
方法可使得一個對象沒法添加新屬性、沒法刪除舊屬性、也沒法改變屬性的值,使得這個對象實際上變成了常量。
Object.isFrozen
方法用於檢查一個對象是否使用了Object.freeze
方法。
上面的三個方法鎖定對象的可寫性有一個漏洞:能夠經過改變原型對象,來爲對象增長屬性。
一種解決方案是,把obj
的原型也凍結住。
另一個侷限是,若是屬性值是對象,上面這些方法只能凍結屬性指向的對象,而不能凍結對象自己的內容。
var obj = {
foo: 1,
bar: ['a', 'b']
};
Object.freeze(obj);
obj.bar.push('c');
obj.bar // ["a", "b", "c"]
複製代碼
上面代碼中,obj.bar
屬性指向一個數組,obj
對象被凍結之後,這個指向沒法改變,即沒法指向其餘值,可是所指向的數組是能夠改變的。
Array
是 JavaScript 的原生對象,同時也是一個構造函數,能夠用它生成新的數組。
Array
構造函數有一個很大的缺陷,就是不一樣的參數,會致使它的行爲不一致。
// 無參數時,返回一個空數組
new Array() // []
// 單個正整數參數,表示返回的新數組的長度
new Array(1) // [ empty ]
new Array(2) // [ empty x 2 ]
// 非正整數的數值做爲參數,會報錯
new Array(3.2) // RangeError: Invalid array length
new Array(-3) // RangeError: Invalid array length
// 單個非數值(好比字符串、布爾值、對象等)做爲參數,
// 則該參數是返回的新數組的成員
new Array('abc') // ['abc']
new Array([1]) // [Array[1]]
// 多參數時,全部參數都是返回的新數組的成員
new Array(1, 2) // [1, 2]
new Array('a', 'b', 'c') // ['a', 'b', 'c']
複製代碼
因此不建議使用構造函數建立數組,推薦用字面量建立
Array.isArray
方法返回一個布爾值,表示參數是否爲數組。它能夠彌補typeof
運算符的不足。
valueOf
方法是一個全部對象都擁有的方法,表示對該對象求值。不一樣對象的valueOf
方法不盡一致,數組的valueOf
方法返回數組自己。
toString
方法也是對象的通用方法,數組的toString
方法返回數組的字符串形式。
push
方法用於在數組的末端添加一個或多個元素,並返回添加新元素後的數組長度。注意,該方法會改變原數組。
pop
方法用於刪除數組的最後一個元素,並返回該元素。注意,該方法會改變原數組。
push
和pop
結合使用,就構成了「後進先出」的棧結構(stack)。
shift()
方法用於刪除數組的第一個元素,並返回該元素。注意,該方法會改變原數組。push()
和shift()
結合使用,就構成了「先進先出」的隊列結構(queue)。
unshift()
方法用於在數組的第一個位置添加元素,並返回添加新元素後的數組長度。注意,該方法會改變原數組。
join()
方法以指定參數做爲分隔符,將全部數組成員鏈接爲一個字符串返回。若是不提供參數,默認用逗號分隔。
concat
方法用於多個數組的合併。它將新數組的成員,添加到原數組成員的後部,而後返回一個新數組,原數組不變。
reverse
方法用於顛倒排列數組元素,返回改變後的數組。注意,該方法將改變原數組。
slice
方法用於提取目標數組的一部分,返回一個新數組,原數組不變。
它的第一個參數爲起始位置(從0開始),第二個參數爲終止位置(但該位置的元素自己不包括在內)。若是省略第二個參數,則一直返回到原數組的最後一個成員。
splice
方法用於刪除原數組的一部分紅員,並能夠在刪除的位置添加新的數組成員,返回值是被刪除的元素。注意,該方法會改變原數組。
splice
的第一個參數是刪除的起始位置(從0開始),第二個參數是被刪除的元素個數。若是後面還有更多的參數,則表示這些就是要被插入數組的新元素。
sort
方法對數組成員進行排序,默認是按照字典順序排序。排序後,原數組將被改變。
map
方法將數組的全部成員依次傳入參數函數,而後把每一次的執行結果組成一個新數組返回。
map
方法還能夠接受第二個參數,用來綁定回調函數內部的this
變量(詳見《this 變量》一章)。
var arr = ['a', 'b', 'c'];
[1, 2].map(function (e) {
return this[e];
}, arr)
// ['b', 'c']
複製代碼
上面代碼經過map
方法的第二個參數,將回調函數內部的this
對象,指向arr
數組。
若是數組有空位,map
方法的回調函數在這個位置不會執行,會跳過數組的空位。
var f = function (n) { return 'a' };
[1, undefined, 2].map(f) // ["a", "a", "a"]
[1, null, 2].map(f) // ["a", "a", "a"]
[1, , 2].map(f) // ["a", , "a"]
複製代碼
filter
方法用於過濾數組成員,知足條件的成員組成一個新數組返回。
some
方法是隻要一個成員的返回值是true
,則整個some
方法的返回值就是true
,不然返回false
。
some
方法是隻要一個成員的返回值是true
,則整個some
方法的返回值就是true
,不然返回false
。
reduce
方法和reduceRight
方法依次處理數組的每一個成員,最終累計爲一個值。它們的差異是,reduce
是從左到右處理(從第一個成員到最後一個成員),reduceRight
則是從右到左(從最後一個成員到第一個成員),其餘徹底同樣。
reduce
方法和reduceRight
方法的第一個參數都是一個函數。該函數接受如下四個參數。
indexOf
方法返回給定元素在數組中第一次出現的位置,若是沒有出現則返回-1
lastIndexOf
方法返回給定元素在數組中最後一次出現的位置,若是沒有出現則返回-1
。
返回值是數組的能夠進行鏈式使用
對象是 JavaScript 語言最主要的數據類型,三種原始類型的值——數值、字符串、布爾值——在必定條件下,也會自動轉爲對象,也就是原始類型的「包裝對象」(wrapper)。
所謂「包裝對象」,指的是與數值、字符串、布爾值分別相對應的Number
、String
、Boolean
三個原生對象。這三個原生對象能夠把原始類型的值變成(包裝成)對象。
上面代碼中,基於原始類型的值,生成了三個對應的包裝對象。能夠看到,v1
、v2
、v3
都是對象,且與對應的簡單類型值不相等。
包裝對象的設計目的,首先是使得「對象」這種類型能夠覆蓋 JavaScript 全部的值,整門語言有一個通用的數據模型,其次是使得原始類型的值也有辦法調用本身的方法。
Number
、String
和Boolean
這三個原生對象,若是不做爲構造函數調用(即調用時不加new
),而是做爲普通函數調用,經常用於將任意類型的值轉爲數值、字符串和布爾值。
某些場合,原始類型的值會自動看成包裝對象調用,即調用包裝對象的屬性和方法。這時,JavaScript 引擎會自動將原始類型的值轉爲包裝對象實例,並在使用後馬上銷燬實例。
好比,字符串能夠調用length
屬性,返回字符串的長度。
'abc'.length // 3
複製代碼
上面代碼中,abc
是一個字符串,自己不是對象,不能調用length
屬性。JavaScript 引擎自動將其轉爲包裝對象,在這個對象上調用length
屬性。調用結束後,這個臨時對象就會被銷燬。這就叫原始類型與實例對象的自動轉換。
自動轉換生成的包裝對象是隻讀的,沒法修改。因此,字符串沒法添加新屬性。
var s = 'Hello World';
s.x = 123;
s.x // undefined
複製代碼
上面代碼爲字符串s
添加了一個x
屬性,結果無效,老是返回undefined
。
另外一方面,調用結束後,包裝對象實例會自動銷燬。這意味着,下一次調用字符串的屬性時,實際是調用一個新生成的對象,而不是上一次調用時生成的那個對象,因此取不到賦值在上一個對象的屬性。若是要爲字符串添加屬性,只有在它的原型對象String.prototype
上定義(參見《面向對象編程》章節)。
除了原生的實例方法,包裝對象還能夠自定義方法和屬性,供原始類型的值直接調用。(標準規範不推薦的)
String.prototype.double = function () {
return this.valueOf() + this.valueOf();
};
'abc'.double()
// abcabc
Number.prototype.double = function () {
return this.valueOf() + this.valueOf();
};
(123).double() // 246
複製代碼
上面代碼在String
和Number
這兩個對象的原型上面,分別自定義了一個方法,從而能夠在全部實例對象上調用。注意,最後一張的123
外面必需要加上圓括號,不然後面的點運算符(.
)會被解釋成小數點。
Number
對象是數值對應的包裝對象
Number.POSITIVE_INFINITY
:正的無限,指向Infinity
。Number.NEGATIVE_INFINITY
:負的無限,指向-Infinity
。Number.NaN
:表示非數值,指向NaN
。Number.MIN_VALUE
:表示最小的正數(即最接近0的正數,在64位浮點數體系中爲5e-324
),相應的,最接近0的負數爲-Number.MIN_VALUE
。Number.MAX_SAFE_INTEGER
:表示可以精確表示的最大整數,即9007199254740991
。Number.MIN_SAFE_INTEGER
:表示可以精確表示的最小整數,即-9007199254740991
。 Number.prototype.toString()
Number
對象部署了本身的toString
方法,用來將一個數值轉爲字符串形式。
(10).toString() // "10"
複製代碼
Number
對象部署了本身的toString
方法,用來將一個數值轉爲字符串形式。
(10).toString() // "10"
複製代碼
Number.prototype.toFixed()
toFixed()
方法先將一個數轉爲指定位數的小數,而後返回這個小數對應的字符串。
(10).toFixed(2) // "10.00"
複製代碼
因爲浮點數的緣由,小數5
的四捨五入是不肯定的,使用的時候必須當心。
(10.055).toFixed(2) // 10.05
(10.005).toFixed(2) // 10.01
複製代碼
Number.prototype.toExponential()
toExponential
方法用於將一個數轉爲科學計數法形式。
toExponential
方法的參數是小數點後有效數字的位數,範圍爲0到20,超出這個範圍,會拋出一個 RangeError 錯誤。
Number.prototype.toPrecision()
toPrecision
方法用於將一個數轉爲指定位數的有效數字。
(12.34).toPrecision(1) // "1e+1"
(12.34).toPrecision(2) // "12"
(12.34).toPrecision(3) // "12.3"
(12.34).toPrecision(4) // "12.34"
(12.34).toPrecision(5) // "12.340"
複製代碼
toPrecision
方法的參數爲有效數字的位數,範圍是1到21,超出這個範圍會拋出 RangeError 錯誤。
String.fromCharCode()
String
對象提供的靜態方法(即定義在對象自己,而不是定義在對象實例的方法),主要是String.fromCharCode()
。該方法的參數是一個或多個數值,表明 Unicode 碼點,返回值是這些碼點組成的字符串。
charAt
方法返回指定位置的字符,參數是從0
開始編號的位置。
若是參數爲負數,或大於等於字符串的長度,charAt
返回空字符串。
charCodeAt
方法返回字符串指定位置的 Unicode 碼點(十進制表示),至關於String.fromCharCode()
的逆操做。
concat
方法用於鏈接兩個字符串,返回一個新字符串,不改變原字符串。
slice
方法用於從原字符串取出子字符串並返回,不改變原字符串。它的第一個參數是子字符串的開始位置,第二個參數是子字符串的結束位置(不含該位置)。
substring
方法用於從原字符串取出子字符串並返回,不改變原字符串,跟slice
方法很相像。它的第一個參數表示子字符串的開始位置,第二個位置表示結束位置(返回結果不含該位置)
substring
方法用於從原字符串取出子字符串並返回,不改變原字符串,跟slice
方法很相像。它的第一個參數表示子字符串的開始位置,第二個位置表示結束位置(返回結果不含該位置)
indexOf
方法用於肯定一個字符串在另外一個字符串中第一次出現的位置,返回結果是匹配開始的位置。若是返回-1
,就表示不匹配。
trim
方法用於去除字符串兩端的空格,返回一個新字符串,不改變原字符串。
該方法去除的不只是空格,還包括製表符(\t
、\v
)、換行符(\n
)和回車符(\r
)。
'\r\nabc \t'.trim() // 'abc'
複製代碼
toLowerCase
方法用於將一個字符串所有轉爲小寫,toUpperCase
則是所有轉爲大寫。它們都返回一個新字符串,不改變原字符串。
match
方法用於肯定原字符串是否匹配某個子字符串,返回一個數組,成員爲匹配的第一個字符串。若是沒有找到匹配,則返回null
。
search
方法的用法基本等同於match
,可是返回值爲匹配的第一個位置。若是沒有找到匹配,則返回-1
。
replace
方法用於替換匹配的子字符串,通常狀況下只替換第一個匹配(除非使用帶有g
修飾符的正則表達式)。
split
方法按照給定規則分割字符串,返回一個由分割出來的子字符串組成的數組。
上面代碼中,split
方法的第二個參數,決定了返回數組的成員數。
split
方法還可使用正則表達式做爲參數,詳見《正則表達式》一節。
Date.parse()方法解析的字符串,均可以看成Date構造函數的參數
new Date('2013-2-15')
new Date('2013/2/15')
new Date('02/15/2013')
new Date('2013-FEB-15')
new Date('FEB, 15, 2013')
new Date('FEB 15, 2013')
new Date('February, 15, 2013')
new Date('February 15, 2013')
new Date('15 Feb 2013')
new Date('15, February, 2013')
複製代碼
多參數模式
new Date(2013, 0)
// Tue Jan 01 2013 00:00:00 GMT+0800 (CST)
new Date(2013, 0, 1)
// Tue Jan 01 2013 00:00:00 GMT+0800 (CST)
new Date(2013, 0, 1, 0)
// Tue Jan 01 2013 00:00:00 GMT+0800 (CST)
new Date(2013, 0, 1, 0, 0, 0, 0)
// Tue Jan 01 2013 00:00:00 GMT+0800 (CST)
複製代碼
上面代碼中,無論有幾個參數,返回的都是2013年1月1日零點。
最後,各個參數的取值範圍以下。
2000
。若是寫成兩位數或個位數,則加上1900
,即10
表明1910年。若是是負數,表示公元前。0
表示一月,依次類推,11
表示12月。1
到31
。0
到23
。0
到59
。0
到59
0
到999
。var d1 = new Date(2000, 2, 1);
var d2 = new Date(2000, 3, 1);
d2 - d1
// 2678400000
d2 + d1
// "Sat Apr 01 2000 00:00:00 GMT+0800 (CST)Wed Mar 01 2000 00:00:00 GMT+0800 (CST)"
複製代碼
Date.now
方法返回當前時間距離時間零點(1970年1月1日 00:00:00 UTC)的毫秒數,至關於 Unix 時間戳乘以1000。
Date.parse
方法用來解析日期字符串,返回該時間距離時間零點(1970年1月1日 00:00:00)的毫秒數。
Date.UTC
方法接受年、月、日等變量做爲參數,返回該時間距離時間零點(1970年1月1日 00:00:00 UTC)的毫秒數。
toJSON
方法返回一個符合 JSON 格式的 ISO 日期字符串,與toISOString
方法的返回結果徹底相同。
toDateString
方法返回日期字符串(不含小時、分和秒)。
toTimeString
方法返回時間字符串(不含年月日)。
Date.prototype.toLocaleString()
:完整的本地時間。Date.prototype.toLocaleDateString()
:本地日期(不含小時、分和秒)。Date.prototype.toLocaleTimeString()
:本地時間(不含年月日)。var d = new Date(2013, 0, 1);
// 時間格式
// 下面的設置是,星期和月份爲完整文字,年份和日期爲數字
d.toLocaleDateString('en-US', {
weekday: 'long',
year: 'numeric',
month: 'long',
day: 'numeric'
})
// "Tuesday, January 1, 2013"
// 指定時區
d.toLocaleTimeString('en-US', {
timeZone: 'UTC',
timeZoneName: 'short'
})
// "4:00:00 PM UTC"
d.toLocaleTimeString('en-US', {
timeZone: 'Asia/Shanghai',
timeZoneName: 'long'
})
// "12:00:00 AM China Standard Time"
// 小時週期爲12仍是24
d.toLocaleTimeString('en-US', {
hour12: false
})
// "00:00:00"
d.toLocaleTimeString('en-US', {
hour12: true
})
// "12:00:00 AM"
複製代碼
getTime()
:返回實例距離1970年1月1日00:00:00的毫秒數,等同於valueOf
方法。getDate()
:返回實例對象對應每月的幾號(從1開始)。getDay()
:返回星期幾,星期日爲0,星期一爲1,以此類推。getFullYear()
:返回四位的年份。getMonth()
:返回月份(0表示1月,11表示12月)。getHours()
:返回小時(0-23)。getMilliseconds()
:返回毫秒(0-999)。getMinutes()
:返回分鐘(0-59)。getSeconds()
:返回秒(0-59)。getTimezoneOffset()
:返回當前時間與 UTC 的時區差別,以分鐘表示,返回結果考慮到了夏令時因素。面這些get*
方法返回的都是當前時區的時間,Date
對象還提供了這些方法對應的 UTC 版本,用來返回 UTC 時間。
getUTCDate()
getUTCFullYear()
getUTCMonth()
getUTCDay()
getUTCHours()
getUTCMinutes()
getUTCSeconds()
getUTCMilliseconds()
setDate(date)
:設置實例對象對應的每月的幾號(1-31),返回改變後毫秒時間戳。setFullYear(year [, month, date])
:設置四位年份。setHours(hour [, min, sec, ms])
:設置小時(0-23)。setMilliseconds()
:設置毫秒(0-999)。setMinutes(min [, sec, ms])
:設置分鐘(0-59)。setMonth(month [, date])
:設置月份(0-11)。setSeconds(sec [, ms])
:設置秒(0-59)。setTime(milliseconds)
:設置毫秒時間戳。set*
系列方法除了setTime()
,都有對應的 UTC 版本,即設置 UTC 時區的時間。
setUTCDate()
setUTCFullYear()
setUTCHours()
setUTCMilliseconds()
setUTCMinutes()
setUTCMonth()
setUTCSeconds()
JavaScript 的正則表達式體系是參照 Perl 5 創建的
新建正則表達式有兩種方法。一種是使用字面量,以斜槓表示開始和結束。
var regex = /xyz/;
複製代碼
另外一種是使用RegExp
構造函數。
var regex = new RegExp('xyz');
複製代碼
它們的主要區別是,第一種方法在引擎編譯代碼時,就會新建正則表達式,第二種方法在運行時新建正則表達式,因此前者的效率較高。並且,前者比較便利和直觀,因此實際應用中,基本上都採用字面量定義正則表達式。
RegExp
構造函數還能夠接受第二個參數,表示修飾符(詳細解釋見下文)。
var regex = new RegExp('xyz', 'i');
// 等價於
var regex = /xyz/i;
複製代碼
RegExp.prototype.ignoreCase
:返回一個布爾值,表示是否設置了i
修飾符。RegExp.prototype.global
:返回一個布爾值,表示是否設置了g
修飾符。RegExp.prototype.multiline
:返回一個布爾值,表示是否設置了m
修飾符。RegExp.prototype.flags
:返回一個字符串,包含了已經設置的全部修飾符,按字母排序。上面四個屬性都是隻讀的。
var r = /abc/igm;
r.ignoreCase // true
r.global // true
r.multiline // true
r.flags // 'gim'
複製代碼
RegExp.prototype.lastIndex
:返回一個整數,表示下一次開始搜索的位置。該屬性可讀寫,可是隻在進行連續搜索時有意義,詳細介紹請看後文。RegExp.prototype.source
:返回正則表達式的字符串形式(不包括反斜槓),該屬性只讀。var r = /abc/igm;
r.lastIndex // 0
r.source // "abc"
複製代碼
正則實例對象的test
方法返回一個布爾值,表示當前模式是否能匹配參數字符串。
/cat/.test('cats and dogs') // true
複製代碼
若是正則表達式帶有g
修飾符,則每一次test
方法都從上一次結束的位置開始向後匹配。
var r = /x/g;
var s = '_x_x';
r.lastIndex // 0
r.test(s) // true
r.lastIndex // 2
r.test(s) // true
r.lastIndex // 4
r.test(s) // false
複製代碼
帶有g
修飾符時,正則表達式內部會記住上一次的lastIndex
屬性,這時不該該更換所要匹配的字符串,不然會有一些難以察覺的錯誤。
正則實例對象的exec
方法,用來返回匹配結果。若是發現匹配,就返回一個數組,成員是匹配成功的子字符串,不然返回null
。
var s = '_x_x';
var r1 = /x/;
var r2 = /y/;
r1.exec(s) // ["x"]
r2.exec(s) // null
複製代碼
replace
方法的一個應用,就是消除字符串首尾兩端的空格。
var str = ' #id div.class ';
str.replace(/^\s+|\s+$/g, '')
// "#id div.class"
複製代碼
replace
方法的第二個參數可使用美圓符號$
,用來指代所替換的內容。
$&
:匹配的子字符串。$'
:匹配結果後面的文本。$n
:匹配成功的第n
組內容,n
是從1開始的天然數。$$
:指代美圓符號$
。'hello world'.replace(/(\w+)\s(\w+)/, '$2 $1')
// "world hello"
'abc'.replace('b', '[$`-$&-$\']') // "a[a-b-c]c" 複製代碼
上面代碼中,第一個例子是將匹配的組互換位置,第二個例子是改寫匹配的值。
replace
方法的第二個參數還能夠是一個函數,將每個匹配內容替換爲函數返回值。
'3 and 5'.replace(/[0-9]+/g, function (match) {
return 2 * match;
})
// "6 and 10"
var a = 'The quick brown fox jumped over the lazy dog.';
var pattern = /quick|brown|lazy/ig;
a.replace(pattern, function replacer(match) {
return match.toUpperCase();
});
// The QUICK BROWN fox jumped over the LAZY dog.
複製代碼
下面是一個網頁模板替換的例子。
var prices = {
'p1': '$1.99',
'p2': '$9.99',
'p3': '$5.00'
};
var template = '<span id="p1"></span>'
+ '<span id="p2"></span>'
+ '<span id="p3"></span>';
template.replace(
/(<span id=")(.*?)(">)(<\/span>)/g,
function(match, $1, $2, $3, $4){
return $1 + $2 + $3 + prices[$2] + $4;
}
);
// "<span id="p1">$1.99</span><span id="p2">$9.99</span><span id="p3">$5.00</span>"
複製代碼
上面代碼的捕捉模式中,有四個括號,因此會產生四個組匹配,在匹配函數中用$1
到$4
表示。匹配函數的做用是將價格插入模板中。
JSON 格式(JavaScript Object Notation 的縮寫)是一種用於數據交換的文本格式,2001年由 Douglas Crockford 提出,目的是取代繁瑣笨重的 XML 格式。
每一個 JSON 對象就是一個值,多是一個數組或對象,也多是一個原始類型的值。總之,只能是一個值,不能是兩個或更多的值。
JSON 對值的類型和格式有嚴格的規定。
- 複合類型的值只能是數組或對象,不能是函數、正則表達式對象、日期對象。
- 原始類型的值只有四種:字符串、數值(必須以十進制表示)、布爾值和
null
(不能使用NaN
,Infinity
,-Infinity
和undefined
)。- 字符串必須使用雙引號表示,不能使用單引號。
- 對象的鍵名必須放在雙引號裏面。
- 數組或對象最後一個成員的後面,不能加逗號。
JSON.stringify
方法用於將一個值轉爲 JSON 字符串。該字符串符合 JSON 格式,而且能夠被JSON.parse
方法還原。
若是對象的屬性是undefined
、函數或 XML 對象,該屬性會被JSON.stringify
過濾。
若是數組的成員是undefined
、函數或 XML 對象,則這些值被轉成null
。
JSON.stringify
方法還能夠接受一個數組,做爲第二個參數,指定須要轉成字符串的屬性。
var obj = {
'prop1': 'value1',
'prop2': 'value2',
'prop3': 'value3'
};
var selectedProperties = ['prop1', 'prop2'];
JSON.stringify(obj, selectedProperties)
// "{"prop1":"value1","prop2":"value2"}"
複製代碼
這個相似白名單的數組,只對對象的屬性有效,對數組無效。
第二個參數還能夠是一個函數,用來更改JSON.stringify
的返回值。
JSON.stringify
還能夠接受第三個參數,用於增長返回的 JSON 字符串的可讀性。若是是數字,表示每一個屬性前面添加的空格(最多不超過10個);若是是字符串(不超過10個字符),則該字符串會添加在每行前面。
JSON.stringify({ p1: 1, p2: 2 }, null, 2);
/* "{ "p1": 1, "p2": 2 }" */
JSON.stringify({ p1:1, p2:2 }, null, '|-');
/* "{ |-"p1": 1, |-"p2": 2 }" */
複製代碼
若是參數對象有自定義的toJSON
方法,那麼JSON.stringify
會使用這個方法的返回值做爲參數,而忽略原對象的其餘屬性。
var user = {
firstName: '三',
lastName: '張',
get fullName(){
return this.lastName + this.firstName;
},
toJSON: function () {
return {
name: this.lastName + this.firstName
};
}
};
JSON.stringify(user)
// "{"name":"張三"}"
複製代碼
toJSON
方法的一個應用是,將正則對象自動轉爲字符串。由於JSON.stringify
默認不能轉換正則對象,可是設置了toJSON
方法之後,就能夠轉換正則對象了。
var obj = {
reg: /foo/
};
// 不設置 toJSON 方法時
JSON.stringify(obj) // "{"reg":{}}"
// 設置 toJSON 方法時
RegExp.prototype.toJSON = RegExp.prototype.toString;
JSON.stringify(/foo/) // ""/foo/""
複製代碼
爲了處理解析錯誤,能夠將JSON.parse
方法放在try...catch
代碼塊中。
try {
JSON.parse("'String'");
} catch(e) {
console.log('parsing error');
}
複製代碼
JSON.parse
方法能夠接受一個處理函數,做爲第二個參數,用法與JSON.stringify
方法相似。
function f(key, value) {
if (key === 'a') {
return value + 10;
}
return value;
}
JSON.parse('{"a": 1, "b": 2}', f)
// {a: 11, b: 2}
複製代碼
能夠作反向操做