在JS中用typeof操作符獲取對(duì)象的類型佩研,它總是返回一個(gè)字符串:
typeof 123; // 'number'
typeof NaN; // 'number'
typeof 'str'; // 'string'
typeof true; // 'boolean'
typeof undefined; // 'undefined'
typeof Math.abs; // 'function'
typeof null; // 'object'
typeof []; // 'object'
typeof {}; // 'object'
其中number享完、string、boolean废膘、function和undefined是基本數(shù)據(jù)類型竹海,我們注意到null的類型是object,Array的類型也是object丐黄,如果我們用typeof將無法區(qū)分出null斋配、Array和通常意義上的object。除此以外灌闺,JS還提供了包裝對(duì)象艰争,number、boolean和string都有包裝對(duì)象桂对,包裝對(duì)象用new創(chuàng)建:
var n = new Number(123); // 123,生成了新的包裝類型
var b = new Boolean(true); // true,生成了新的包裝類型
var s = new String('str'); // 'str',生成了新的包裝類型
雖然包裝對(duì)象看上去和原來一模一樣甩卓,但他們的類型已經(jīng)變?yōu)閛bject了!所以包裝對(duì)象和原始值用===比較會(huì)返回false蕉斜,一般情況下不要使用包裝對(duì)象逾柿,尤其是string類型:
typeof new Number(123); // 'object'
new Number(123) === 123; // false
typeof new Boolean(true); // 'object'
new Boolean(true) === true; // false
typeof new String('str'); // 'object'
new String('str') === 'str'; // false
此外,Number()宅此、Boolean和String()作為普通函數(shù)机错,把任何類型的數(shù)據(jù)轉(zhuǎn)換為其相應(yīng)類型(注意不是包裝類型):
var n = Number('123'); // 123,相當(dāng)于parseInt()或parseFloat()
typeof n; // 'number'
var b = Boolean('true'); // true
typeof b; // 'boolean'
var b2 = Boolean('false'); // true! 'false'字符串轉(zhuǎn)換結(jié)果為true诽凌!因?yàn)樗欠强兆址?var b3 = Boolean(''); // false
var s = String(123.45); // '123.45'
typeof s; // 'string'
對(duì)JS中數(shù)據(jù)類型稍作總結(jié)如下:
- 不要使用new Number()毡熏、new Boolean()、new String()創(chuàng)建包裝對(duì)象侣诵;
- 用parseInt()或parseFloat()來轉(zhuǎn)換任意類型到number痢法;
- 用String()來轉(zhuǎn)換任意類型到string,或者直接調(diào)用某個(gè)對(duì)象的toString()方法杜顺;
- 通常不必把任意類型轉(zhuǎn)換為boolean再判斷财搁,因?yàn)榭梢灾苯訉慽f (myVar) {...};
- typeof操作符可以判斷區(qū)分number躬络、boolean尖奔、string、function和undefined;
- 判斷Array要使用Array.isArray(arr)提茁;
- 判斷null請(qǐng)使用myVar === null淹禾;
- 判斷全局變量是否存在用typeof window.myVar === 'undefined';
- 函數(shù)內(nèi)部判斷變量是否存在用typeof myVar === 'undefined'茴扁。
最后需要指出null和undefined沒有toString()铃岔,number對(duì)象調(diào)用toString()要特殊處理一下:
123.toString(); // SyntaxError
123..toString(); // '123', 注意是兩個(gè)點(diǎn)!
(123).toString(); // '123'
Date
在JS中Date對(duì)象用來表示日期和時(shí)間:
var now = new Date();
now; // Wed Jun 24 2015 19:49:22 GMT+0800 (CST)
now.getFullYear(); // 2015, 年份
now.getMonth(); // 5, 月份峭火,注意月份范圍是0~11毁习,5表示六月
now.getDate(); // 24, 表示24號(hào)
now.getDay(); // 3, 表示星期三
now.getHours(); // 19, 24小時(shí)制
now.getMinutes(); // 49, 分鐘
now.getSeconds(); // 22, 秒
now.getMilliseconds(); // 875, 毫秒數(shù)
now.getTime(); // 1435146562875, 以number形式表示的時(shí)間戳
注意,當(dāng)前時(shí)間是瀏覽器從本機(jī)操作系統(tǒng)獲取的時(shí)間卖丸,所以不一定準(zhǔn)確纺且,如果要?jiǎng)?chuàng)建一個(gè)指定日期和時(shí)間的Date對(duì)象,可以用:
var d = new Date(2015, 5, 19, 20, 15, 30, 123);
d; // Fri Jun 19 2015 20:15:30 GMT+0800 (CST)
var timestamp = Date.parse('2015-06-24T19:49:22.875+08:00');
// 這里返回一個(gè)時(shí)間戳稍浆,再轉(zhuǎn)換為Date:
timestamp; // 1435146562875
var date = new Date(timestamp);
date; // Wed Jun 24 2015 19:49:22 GMT+0800 (CST)
date.toLocaleString(); // '2015/6/24 下午7:49:22'载碌,本地時(shí)間(北京時(shí)區(qū)+8:00),顯示的字符串與操作系統(tǒng)設(shè)定的格式有關(guān)
date.toUTCString(); // 'Wed, 24 Jun 2015 11:49:22 GMT'衅枫,UTC時(shí)間恐仑,與本地時(shí)間相差8小時(shí)
需要強(qiáng)調(diào)的是JS中月份范圍用整數(shù)表示是0~11,從0開始为鳄。我們只需要從數(shù)據(jù)庫(kù)讀取時(shí)間戳,再轉(zhuǎn)換為當(dāng)?shù)貢r(shí)間:
if (Date.now) {
alert(Date.now()); // 老版本IE沒有now()方法
} else {
alert(new Date().getTime());
}
RegExp
JS中創(chuàng)建正則表達(dá)式有兩種方式腕让,第一種方式是直接通過/正則表達(dá)式/寫出來孤钦,第二種方式是通過new RegExp('正則表達(dá)式')創(chuàng)建一個(gè)RegExp對(duì)象:
var re1 = /ABC\-001/;
var re2 = new RegExp('ABC\\-001');
re1; // /ABC\-001/
re2; // /ABC\-001/
RegExp對(duì)象的test()方法用于測(cè)試給定的字符串是否符合條件:
var re = /^\d{3}\-\d{3,8}$/;
re.test('010-12345'); // true
re.test('010-1234x'); // false
re.test('010 12345'); // false
用正則表達(dá)式切分字符串比用固定的字符更靈活:
'a b c'.split(' '); // ['a', 'b', '', '', 'c']
// 用正則表達(dá)式切分
'a b c'.split(/\s+/); // ['a', 'b', 'c']
// 加入,試試
'a,b, c d'.split(/[\s\,]+/); // ['a', 'b', 'c', 'd']
一般用正則表達(dá)式把用戶不規(guī)范的輸入轉(zhuǎn)化成正確的格式進(jìn)行處理。除此之外纯丸,正則表達(dá)式還有提取子串的強(qiáng)大功能偏形,比如:
var re = /^(\d{3})-(\d{3,8})$/;
re.exec('010-12345'); // ['010-12345', '010', '12345']
re.exec('010 12345'); // null
exec()方法在匹配成功后,會(huì)返回一個(gè)Array觉鼻,第一個(gè)元素是正則表達(dá)式匹配到的整個(gè)字符串俊扭,后面的字符串表示匹配成功的子串;exec()方法在匹配失敗時(shí)返回null坠陈。
需要特別指出的是萨惑,正則匹配默認(rèn)是貪婪匹配,也就是匹配盡可能多的字符仇矾。舉例如下:
var re = /^(\d+)(0*)$/;
re.exec('102300'); // ['102300', '102300', '']
由于\d+采用貪婪匹配庸蔼,直接把后面的0全部匹配了,結(jié)果0*只能匹配空字符串了贮匕。必須讓\d+采用非貪婪匹配(也就是盡可能少匹配)姐仅,才能把后面的0匹配出來,加個(gè)?就可以讓\d+采用非貪婪匹配:
var re = /^(\d+?)(0*)$/;
re.exec('102300'); // ['102300', '1023', '00']
JS的正則表達(dá)式還有幾個(gè)特殊的標(biāo)志,最常用的是g表示全局匹配掏膏,i表示忽略大小寫劳翰,m表示執(zhí)行多行匹配:
var r1 = /test/g;
// 等價(jià)于:
var r2 = new RegExp('test', 'g');
全局匹配可以多次執(zhí)行exec()方法來搜索一個(gè)匹配的字符串,不能使用/^...$/馒疹,那樣只會(huì)最多匹配一次佳簸。當(dāng)我們指定g標(biāo)志后,每次運(yùn)行exec()行冰,正則表達(dá)式本身會(huì)更新lastIndex屬性溺蕉,表示上次匹配到的最后索引:
var s = 'JavaScript, VBScript, JScript and ECMAScript';
var re=/[a-zA-Z]+Script/g;
// 使用全局匹配:
re.exec(s); // ['JavaScript']
re.lastIndex; // 10
re.exec(s); // ['VBScript']
re.lastIndex; // 20
re.exec(s); // ['JScript']
re.lastIndex; // 29
re.exec(s); // ['ECMAScript']
re.lastIndex; // 44
re.exec(s); // null,直到結(jié)束仍沒有匹配到
JSON
JSON實(shí)際上是JavaScript的一個(gè)子集悼做,在JS中我們可以直接使用JSON疯特,因?yàn)镴avaScript內(nèi)置了JSON的解析。把任何JavaScript對(duì)象變成JSON肛走,就是把這個(gè)對(duì)象序列化成一個(gè)JSON格式的字符串漓雅,這樣才能夠通過網(wǎng)絡(luò)傳遞給其他計(jì)算機(jī)。如果我們收到一個(gè)JSON格式的字符串朽色,只需要把它反序列化成一個(gè)JavaScript對(duì)象邻吞,就可以在JavaScript中直接使用這個(gè)對(duì)象了。讓我們先把小明這個(gè)對(duì)象序列化成JSON格式的字符串:
var xiaoming = {
name: '小明',
age: 14,
gender: true,
height: 1.65,
grade: null,
'middle-school': '\"W3C\" Middle School',
skills: ['JavaScript', 'Java', 'Python', 'Lisp']
};
JSON.stringify(xiaoming); // '{"name":"小明","age":14,"gender":true,"height":1.65,"grade":null,"middle-school":"\"W3C\" Middle School","skills":["JavaScript","Java","Python","Lisp"]}'
可以加上參數(shù)按縮進(jìn)輸出:
JSON.stringify(xiaoming, null, ' ');
結(jié)果:
{
"name": "小明",
"age": 14,
"gender": true,
"height": 1.65,
"grade": null,
"middle-school": "\"W3C\" Middle School",
"skills": [
"JavaScript",
"Java",
"Python",
"Lisp"
]
}
第二個(gè)參數(shù)用于控制如何篩選對(duì)象的鍵值葫男,如果我們只想輸出指定的屬性抱冷,可以傳入Array:
JSON.stringify(xiaoming, ['name', 'skills'], ' ');
結(jié)果:
{
"name": "小明",
"skills": [
"JavaScript",
"Java",
"Python",
"Lisp"
]
}
還可以傳入一個(gè)函數(shù),這樣對(duì)象的每個(gè)鍵值對(duì)都會(huì)被函數(shù)先處理:
function convert(key, value) {
if (typeof value === 'string') {
return value.toUpperCase();
}
return value;
}
JSON.stringify(xiaoming, convert, ' ');
{
"name": "小明",
"age": 14,
"gender": true,
"height": 1.65,
"grade": null,
"middle-school": "\"W3C\" MIDDLE SCHOOL",
"skills": [
"JAVASCRIPT",
"JAVA",
"PYTHON",
"LISP"
]
}
如果我們還想要精確控制如何序列化小明梢褐,可以給xiaoming定義一個(gè)toJSON()的方法旺遮,直接返回JSON應(yīng)該序列化的數(shù)據(jù):
var xiaoming = {
name: '小明',
age: 14,
gender: true,
height: 1.65,
grade: null,
'middle-school': '\"W3C\" Middle School',
skills: ['JavaScript', 'Java', 'Python', 'Lisp'],
toJSON: function () {
return { // 只輸出name和age,并且改變了key:
'Name': this.name,
'Age': this.age
};
}
};
JSON.stringify(xiaoming); // '{"Name":"小明","Age":14}'
拿到一個(gè)JSON格式的字符串盈咳,我們直接用JSON.parse()把它變成一個(gè)JavaScript對(duì)象:
JSON.parse('[1,2,3,true]'); // [1, 2, 3, true]
JSON.parse('{"name":"小明","age":14}'); // Object {name: '小明', age: 14}
JSON.parse('true'); // true
JSON.parse('123.45'); // 123.45
JSON.parse()還可以接收一個(gè)函數(shù)耿眉,用來轉(zhuǎn)換解析出的屬性:
JSON.parse('{"name":"小明","age":14}', function (key, value) {
// 把number * 2:
if (key === 'name') {
return value + '同學(xué)';
}
return value;
}); // Object {name: '小明同學(xué)', age: 14}