JavaScript學(xué)習(xí)筆記-基本對象

在JS中用typeof操作符獲取對象的類型,它總是返回一個字符串:

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還提供了包裝對象,number、boolean和string都有包裝對象,包裝對象用new創(chuàng)建:

var n = new Number(123); // 123,生成了新的包裝類型
var b = new Boolean(true); // true,生成了新的包裝類型
var s = new String('str'); // 'str',生成了新的包裝類型

雖然包裝對象看上去和原來一模一樣,但他們的類型已經(jīng)變?yōu)閛bject了!所以包裝對象和原始值用===比較會返回false,一般情況下不要使用包裝對象,尤其是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!因為它是非空字符串!
var b3 = Boolean(''); // false

var s = String(123.45); // '123.45'
typeof s; // 'string'

對JS中數(shù)據(jù)類型稍作總結(jié)如下:

  • 不要使用new Number()、new Boolean()、new String()創(chuàng)建包裝對象;
  • 用parseInt()或parseFloat()來轉(zhuǎn)換任意類型到number;
  • 用String()來轉(zhuǎn)換任意類型到string,或者直接調(diào)用某個對象的toString()方法;
  • 通常不必把任意類型轉(zhuǎn)換為boolean再判斷,因為可以直接寫if (myVar) {...};
  • typeof操作符可以判斷區(qū)分number、boolean、string、function和undefined;
  • 判斷Array要使用Array.isArray(arr);
  • 判斷null請使用myVar === null;
  • 判斷全局變量是否存在用typeof window.myVar === 'undefined';
  • 函數(shù)內(nèi)部判斷變量是否存在用typeof myVar === 'undefined'。

最后需要指出null和undefined沒有toString(),number對象調(diào)用toString()要特殊處理一下:

123.toString(); // SyntaxError
123..toString(); // '123', 注意是兩個點!
(123).toString(); // '123'

Date

在JS中Date對象用來表示日期和時間:

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號
now.getDay(); // 3, 表示星期三
now.getHours(); // 19, 24小時制
now.getMinutes(); // 49, 分鐘
now.getSeconds(); // 22, 秒
now.getMilliseconds(); // 875, 毫秒數(shù)
now.getTime(); // 1435146562875, 以number形式表示的時間戳

注意,當(dāng)前時間是瀏覽器從本機操作系統(tǒng)獲取的時間,所以不一定準確,如果要創(chuàng)建一個指定日期和時間的Date對象,可以用:

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');
// 這里返回一個時間戳,再轉(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',本地時間(北京時區(qū)+8:00),顯示的字符串與操作系統(tǒng)設(shè)定的格式有關(guān)
date.toUTCString(); // 'Wed, 24 Jun 2015 11:49:22 GMT',UTC時間,與本地時間相差8小時

需要強調(diào)的是JS中月份范圍用整數(shù)表示是0~11,從0開始。我們只需要從數(shù)據(jù)庫讀取時間戳,再轉(zhuǎn)換為當(dāng)?shù)貢r間:

if (Date.now) {
    alert(Date.now()); // 老版本IE沒有now()方法
} else {
    alert(new Date().getTime());
}

RegExp

JS中創(chuàng)建正則表達式有兩種方式,第一種方式是直接通過/正則表達式/寫出來,第二種方式是通過new RegExp('正則表達式')創(chuàng)建一個RegExp對象:

var re1 = /ABC\-001/;
var re2 = new RegExp('ABC\\-001');

re1; // /ABC\-001/
re2; // /ABC\-001/

RegExp對象的test()方法用于測試給定的字符串是否符合條件:

var re = /^\d{3}\-\d{3,8}$/;
re.test('010-12345'); // true
re.test('010-1234x'); // false
re.test('010 12345'); // false

用正則表達式切分字符串比用固定的字符更靈活:

'a b   c'.split(' '); // ['a', 'b', '', '', 'c']
// 用正則表達式切分
'a b   c'.split(/\s+/); // ['a', 'b', 'c']
// 加入,試試
'a,b, c  d'.split(/[\s\,]+/); // ['a', 'b', 'c', 'd']

一般用正則表達式把用戶不規(guī)范的輸入轉(zhuǎn)化成正確的格式進行處理。除此之外,正則表達式還有提取子串的強大功能,比如:

var re = /^(\d{3})-(\d{3,8})$/;
re.exec('010-12345'); // ['010-12345', '010', '12345']
re.exec('010 12345'); // null

exec()方法在匹配成功后,會返回一個Array,第一個元素是正則表達式匹配到的整個字符串,后面的字符串表示匹配成功的子串;exec()方法在匹配失敗時返回null。
需要特別指出的是,正則匹配默認是貪婪匹配,也就是匹配盡可能多的字符。舉例如下:

var re = /^(\d+)(0*)$/;
re.exec('102300'); // ['102300', '102300', '']

由于\d+采用貪婪匹配,直接把后面的0全部匹配了,結(jié)果0*只能匹配空字符串了。必須讓\d+采用非貪婪匹配(也就是盡可能少匹配),才能把后面的0匹配出來,加個?就可以讓\d+采用非貪婪匹配:

var re = /^(\d+?)(0*)$/;
re.exec('102300'); // ['102300', '1023', '00']

JS的正則表達式還有幾個特殊的標(biāo)志,最常用的是g表示全局匹配,i表示忽略大小寫,m表示執(zhí)行多行匹配:

var r1 = /test/g;
// 等價于:
var r2 = new RegExp('test', 'g');

全局匹配可以多次執(zhí)行exec()方法來搜索一個匹配的字符串,不能使用/^...$/,那樣只會最多匹配一次。當(dāng)我們指定g標(biāo)志后,每次運行exec(),正則表達式本身會更新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實際上是JavaScript的一個子集,在JS中我們可以直接使用JSON,因為JavaScript內(nèi)置了JSON的解析。把任何JavaScript對象變成JSON,就是把這個對象序列化成一個JSON格式的字符串,這樣才能夠通過網(wǎng)絡(luò)傳遞給其他計算機。如果我們收到一個JSON格式的字符串,只需要把它反序列化成一個JavaScript對象,就可以在JavaScript中直接使用這個對象了。讓我們先把小明這個對象序列化成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ù)按縮進輸出:

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"
  ]
}

第二個參數(shù)用于控制如何篩選對象的鍵值,如果我們只想輸出指定的屬性,可以傳入Array:

JSON.stringify(xiaoming, ['name', 'skills'], '  ');
結(jié)果:
{
  "name": "小明",
  "skills": [
    "JavaScript",
    "Java",
    "Python",
    "Lisp"
  ]
}

還可以傳入一個函數(shù),這樣對象的每個鍵值對都會被函數(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定義一個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}'

拿到一個JSON格式的字符串,我們直接用JSON.parse()把它變成一個JavaScript對象:

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()還可以接收一個函數(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}
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

推薦閱讀更多精彩內(nèi)容