JavaScript中的類型轉換(二)

說明: 本篇主要討論JavaScript中各運算符對運算數進行的類型轉換的影響,本文中所提到的對象類型僅指JavaScript預約義的類型和程序員本身實現的對象,不包括宿主環境定義的特殊對象(好比瀏覽器定義的對象)

上一篇中討論了JavaScript中原始類型到原始類型的轉換,原始類型到對象類型的轉換和對象類型到原始類型的轉換,這裏先提出一個問題程序員

var a = undefined;
if(a){
    console.log('hello');
}else{
    console.log('world');
}
console.log(a == false);

之前我不對JavaScript的只知其一;不知其二的時候,我覺得上面的代碼回前後輸出'world'和'true',可是通過執行代碼,發現結果是'world'和'false'.undefined確確實實能夠被轉換爲false,可是在使用==操做符對undefined和false兩個值進行相等性比較時,因爲兩個操做數的類型不一樣,這裏會發生類型轉換,而且undefined並無被轉換爲boolean類型而後跟false比較,因此本篇討論下運算符對運算數類型轉換的影響.瀏覽器

1.+(二元),==,!=,>,<,<=,>=

 

二元+運算符用於把兩個數字相加或者鏈接兩個字符串,因此該運算符指望的運算數類型爲數字或者字符串。當運算數都是數字或者字符串時,結果是顯而易見的,不然的話就會現對操做數進行類型轉換,把操做數轉換爲數字或者字符串,而後進行數學相加或者鏈接字符串的運算。操做數會照下面的規則進行類型轉換:spa

1.若是其中任一操做數是對象類型,先執行對象到原始類型的轉換:對於Date對象,經過調用toString方法獲得原始類型的值;對於其餘對象,優先嚐試valueOf方法,而後再嘗試toString方法,若是valueOf和toString都沒法獲得原始類型的值,則會拋出異常code

2.如今兩個操做數都是原始類型了,若是其中一個操做數是字符串,則把另一個原始類型的操做數轉換成字符串,而後執行字符串鏈接運算對象

3.不然,把兩個操做數都轉換成數字進行數學加法運算blog

console.log('10'+null);//10null
        console.log('10'+undefined);//10undefined
        console.log('10'+false);//10false
        console.log('10'+true);//10true
        console.log('10'+10);//1010
        var o1 = {};
        console.log('10'+o1);//10[object Object] 對象默認的valueOf方法返回的不是原始類型,因此會調用toString方法
        o1.toString = function(){
            return 'o1';
        }
        console.log('10'+o1);//10o1
        o1.valueOf = function(){
            return null;
        }
        console.log('10'+o1);//10null 對象如今有了一個返回原始類型的valueOf方法,再也不調用toStringconsole.log(10+null);
        console.log(10+undefined);//NaN, undefinde轉換成數字是Nan
        console.log(10+false);//10
        console.log(10+true);//11
        var o1 = {};
        console.log(10+o1);//10[object Object] 對象默認的valueOf方法返回的不是原始類型,因此會調用toString方法,而toString返回的是字符串,因此執行字符串鏈接
        o1.toString = function(){
            return true;
        }
        console.log(10+o1);//11
        o1.valueOf = function(){
            return null;
        }
        console.log(10+o1);//10 對象如今有了一個返回原始類型的valueOf方法,再也不調用toString                var date = new Date;
        console.log(date + true);//Tue Aug 19 2014 10:32:49 GMT+0800 (中國標準時間)true
 

使用==運算符比較兩個運算數的相等性時,若是兩個運算數類型不一致,就會發生類型轉換,轉換時遵循如下規則ip

1.null和undefined是相等的字符串

2.若是一個操做數是數字,另外一個操做數是字符串,則把字符串轉換成數字再進行比較數學

3.若是有布爾類型的操做數,把它轉換成數字io

4.若是其中一個操做數是對象類型,把對象類型轉換成原始類型再進行比較.當把對象轉換成原始值時,優先使用valueOf方法,其次使用toString方法,可是與+運算符同樣,Date對象是個特例,Date對象調用toString方法

5.其他狀況一概認爲不想等

到這裏能夠解釋本文開始提出的問題了,undefined與false進行==比較,false先被轉換成數字0,而後與undefined比較,屬於狀況5,返回false

console.log(0 == null);//false
        console.log( 0 == undefined);// false
        console.log(0 == false);//true,false轉換成0
        console.log(1 == true);//true,true轉換成1
        console.log(true == '1');//true,true先轉換成1,而後1轉換成字符串'1'
        console.log(null == 'null');//false,狀況5
        var o = {};
        console.log(o == '[object Object]');//true,toString方法返回'[object Object]'
        o.valueOf = function(){
            return '1';
        };
        console.log(true == o);//true,true先轉換爲1,o先調用valueOf獲得一個原始值'1',數字與字符串比較,數字轉換成字符串

 

 

對於!=運算符,結果老是與==運算符的結果相反

對於>,<(很萌有木有),<=,>=這四個比較運算符,指望的運算數類型與二元+同樣,要麼比較兩個數字,要麼比較兩個字符串,若是運算數不全位數字或字符串,則會發生類型轉換,轉換的規則以下:

1.若是任一操做數是對象類型,則前後嘗試valueOf方法和toString方法把對象轉換成原始類型,須要注意的是這裏Date再也不作特殊處理了,與其餘對象同樣

2.通過第一步以後,兩個操做數都是原始類型了,若是都是字符串,則進行字符串比較,若是都是數字,則進行數字比較

3.不然,把兩個原始類型都轉換成數字,而後進行比較

console.log(1 > null);//true,null->0
        console.log( 1 >= undefined);// false,undefined->NaN
        console.log(1 <= undefined);//false
        console.log(null > undefined) // false,null->0,undefinde->NaN
        console.log(null <= undefined)//false
        console.log('1' < true);//false,'1'->1,true->1
        console.log('1' > true);//false
        var o = {};
        o.toString = function(){
            return 10;
        };
        console.log(o > 9);//true, o->10
        console.log(o > '9')//true,o->10,'9'->9
        o.toString = function(){
            return '10';
        }
        console.log(o > 9);//true, o->'10','10'->10
        console.log(o > '9')//false,o->'10'
        o={};
        var o1={};
        console.log(o > o1);//o和o1都經過toString方法轉換成了字符串,而且字符串內容是一致的
        console.log(o < o1);
        console.log(o >= o1);

2.+(一元),-(一元和二元),*,++,--

這幾個運算符指望的運算數都是數字類型,因此當操做數類型不對時,會把操做數轉換爲數字

var a = '10';
        console.log(+a);//+10
        console.log(1 - a);//-9
        console.log(a++);//10,可是此時a的類型已經發生了變化,++和--都須要一個左值,因此++'10'是錯誤的
        console.log(typeof a);//輸出number,a的類型已經改變
        a = '10';
        var o = {};
        o.toString = function() {
            return '10';
        }
        console.log(o++);//10,o->'10'->10
        console.log(typeof o);//number
        o = {};
        o.toString = function() {
            return '10';
        }
        o.valueOf = function(){
            return false;
        }
        console.log(++o);//1,優先使用valueOf方法
        console.log(typeof o);//number

3.總結

從本文的分析能夠看出,JavaScript中的大部分運算符都只能對原始類型的操做數進行運算,其中一部分只能對數字類型進行運算,另外一部分能夠對數字和字符串類型進行運算,當進行運算時,運算數與預期的類型不相符合時,會經過前後調用valueOf和toString方法將對象類型轉換爲原始類型(須要注意Date對象的特殊性),而後再將原始類型轉換爲數字或者字符串.

相關文章
相關標籤/搜索