js中的強制轉換規則


前言

JavaScript 中共有七種內置數據類型,包括基本類型和對象類型

 

基本類型

基本類型分為以下六種:

  • string(字符串)

  • boolean(布爾值)

  • number(數字)

  • symbol(符號)

  • null(空值)

  • undefined(未定義)

  1. string 、number 、boolean 和 null undefined 這五種類型統稱為原始類型(Primitive),表示不能再細分下去的基本類型

  2. symbol是ES6中新增的數據類型,symbol 表示獨一無二的值,通過 Symbol 函數調用生成,由於生成的 symbol 值為原始類型,所以 Symbol 函數不能使用 new 調用

  3. null 和 undefined 通常被認為是特殊值,這兩種類型的值唯一,就是其本身

 

對象類型

對象類型也叫引用類型,array和function是對象的子類型。對象在邏輯上是屬性的無序集合,是存放各種值的容器。對象值存儲的是引用地址,所以和基本類型值不可變的特性不同,對象值是可變的

 

 

js中的強制轉換規則

ToPrimitive(轉換為原始值)

ToPrimitive對原始類型不發生轉換處理,只針對引用類型(object)的,其目的是將引用類型(object)轉換為非對象類型,也就是原始類型

ToPrimitive 運算符接受一個值,和一個可選的 期望類型作參數。ToPrimitive 運算符將值轉換為非對象類型,如果對象有能力被轉換為不止一種原語類型,可以使用可選的期望類型來暗示那個類型

轉換后的結果原始類型是由期望類型決定的,期望類型其實就是我們傳遞的type。直接看下面比較清楚。ToPrimitive方法大概長這么個樣子具體如下

/**
* @obj 需要轉換的對象
* @type 期望轉換為的原始數據類型,可選
*/
ToPrimitive(obj,type)

 

type不同值的說明

    • type為string

      1. 先調用obj的toString方法,如果為原始值,則return,否則第2步

      2. 調用obj的valueOf方法,如果為原始值,則return,否則第3步

      3. 拋出TypeError 異常

    • type為number

      1. 調用obj的valueOf方法,如果為原始值,則返回,否則下第2步

      2. 調用obj的toString方法,如果為原始值,則return,否則第3步

      3. 拋出TypeError 異常

    • type參數為空

      1. 該對象為Date,則type被設置為String

      2. 否則,type被設置為Number

 

Date數據類型特殊說明

對於Date數據類型,我們更多期望獲得的是其轉為時間后的字符串,而非毫秒值(時間戳),如果為number,則會取到對應的毫秒值,顯然字符串使用更多。其他類型對象按照取值的類型操作即可

 

ToPrimitive總結 

 ToPrimitive轉成何種原始類型,取決於type,type參數可選,若指定,則按照指定類型轉換,若不指定,默認根據實用情況分兩種情況,Date為string,其余對象為number。那么什么時候會指定type類型呢,那就要看下面兩種轉換方式了

 

 

toString

Object.prototype.toString()

toString() 方法返回一個表示該對象的字符串

每個對象都有一個 toString() 方法,當對象被表示為文本值時或者當以期望字符串的方式引用對象時,該方法被自動調用

這里先記住,valueOf() 和 toString() 在特定的場合下會自行調用

 

 

valueOf

Object.prototype.valueOf()方法返回指定對象的原始值

JavaScript 調用 valueOf() 方法用來把對象轉換成原始類型的值(數值、字符串和布爾值)。但是我們很少需要自己調用此函數,valueOf 方法一般都會被 JavaScript 自動調用

不同內置對象的valueOf實現

  • String => 返回字符串值

  • Number => 返回數字值

  • Date => 返回一個數字,即時間值,字符串中內容是依賴於具體實現的

  • Boolean => 返回Boolean的this值

  • Object => 返回this

代碼對照

const str = newString('123');
console.log(str.valueOf());//123
​
const num = newNumber(123);
console.log(num.valueOf());//123
​
const date = newDate();
console.log(date.valueOf()); //1526990889729
​
const bool = newBoolean('123');
console.log(bool.valueOf());//true
​
const obj = newObject({valueOf:()=>{
    return1
}})
console.log(obj.valueOf());//1

 

 

Number

Number運算符轉換規則

  • null 轉換為 0

  • undefined 轉換為 NaN

  • true 轉換為 1,false 轉換為 0

  • 字符串轉換時遵循數字常量規則,轉換失敗返回 NaN

對象這里要先轉換為原始值,調用ToPrimitive轉換,type指定為number了,繼續回到ToPrimitive進行轉換(看ToPrimitive)

 

 

String

String 運算符轉換規則

  • null 轉換為 'null'

  • undefined 轉換為 undefined

  • true 轉換為 'true',false 轉換為 'false'

  • 數字轉換遵循通用規則,極大極小的數字使用指數形式

對象這里要先轉換為原始值,調用ToPrimitive轉換,type就指定為string了,繼續回到ToPrimitive進行轉換(看ToPrimitive)

String(null)                 // 'null'
String(undefined)            // 'undefined'
String(true)                 // 'true'
String(1)                    // '1'
String(-1)                   // '-1'
String(0)                    // '0'
String(-0)                   // '0'
String(Math.pow(1000,10))    // '1e+30'
String(Infinity)             // 'Infinity'
String(-Infinity)            // '-Infinity'
String({})                   // '[object Object]'
String([1,[2,3]])            // '1,2,3'
String(['koala',1])          //koala,1
Boolean(undefined) // false
Boolean(null) // false
Boolean(0) // false
Boolean(NaN) // false
Boolean('') // false
Boolean({}) // true
Boolean([]) // true
Boolean(newBoolean(false)) // true

 

 

Boolean

ToBoolean 運算符轉換規則

除了下述 6 個值轉換結果為 false,其他全部為 true

  1. undefined

  2. null

  3. -0

  4. 0或+0

  5. NaN

  6. ''(空字符串)

假值以外的值都是真值。其中包括所有對象(包括空對象)的轉換結果都是true,甚至連false對應的布爾對象new Boolean(false)也是true

Boolean(undefined) // false
Boolean(null) // false
Boolean(0) // false
Boolean(NaN) // false
Boolean('') // false
Boolean({}) // true
Boolean([]) // true
Boolean(newBoolean(false)) // true

 

 

js轉換規則不同場景應用

什么時候自動轉換為string類型

在沒有對象的前提下

字符串的自動轉換,主要發生在字符串的加法運算時。當一個值為字符串,另一個值為非字符串,則后者轉為字符串

'2' + 1// '21'
'2' + true// "2true"
'2' + false// "2false"
'2' + undefined// "2undefined"
'2' + null// "2null"

當有對象且與對象+時候

//toString的對象
var obj2 = {
    toString:function(){
        return'a'
    }
}
console.log('2'+obj2)
//輸出結果2a
​
//常規對象
var obj1 = {
   a:1,
   b:2
}
console.log('2'+obj1);
//輸出結果 2[object Object]
​
//幾種特殊對象
'2' + {} // "2[object Object]"
'2' + [] // "2"
'2' + function (){} // "2function (){}"
'2' + ['koala',1] // 2koala,1

對上面'2'+obj2詳細舉例說明如下

  1. 左邊為string,ToPrimitive原始值轉換后不發生變化

  2. 右邊轉化時同樣按照ToPrimitive進行原始值轉換,由於指定的type是number,進行ToPrimitive轉化調用obj2.valueof(),得到的不是原始值,進行第三步

  3. 調用toString() return 'a'

  4. 符號兩邊存在string,而且是+號運算符則都采用String規則轉換為string類型進行拼接

  5. 輸出結果2a

對上面'2'+obj1詳細舉例說明如下

  1. 左邊為string,ToPrimitive轉換為原始值后不發生變化

  2. 右邊轉化時同樣按照ToPrimitive進行原始值轉換,由於指定的type是number,進行ToPrimitive轉化調用obj2.valueof(),得到{ a: 1, b: 2

  3. 調用toString() return [object Object]

  4. 符號兩邊存在string,而且是+號運算符則都采用String規則轉換為string類型進行拼接

  5. 輸出結果2[object Object]

代碼中幾種特殊對象的轉換規則基本相同,就不一一說明,大家可以想一下流程

不管是對象還不是對象,都有一個轉換為原始值的過程,也就是ToPrimitive轉換,只不過原始類型轉換后不發生變化,對象類型才會發生具體轉換

  

string類型轉換開發過程中常出錯的點

var obj = {
  width: '100'
};
​
obj.width + 20// "10020"

預期輸出結果120 實際輸出結果10020

 

 

什么時候自動轉換為Number類型

  • 有加法運算符,但是無String類型的時候,都會優先轉換為Number類型

    true+0// 1
    true+true// 2
    true+false//1
  • 除了加法運算符,其他運算符都會把運算自動轉成數值

    '5' - '2'// 3
    '5' * '2'// 10
    true - 1// 0
    false - 1// -1
    '1' - 1// 0
    '5' * []    // 0
    false/ '5' // 0
    'abc' - 1   // NaN
    null + 1 // 1
    undefined + 1 // NaN
    ​
    //一元運算符(注意點)
    +'abc' // NaN
    -'abc' // NaN
    +true // 1
    -false // 0
    

    null轉為數值時為0,而undefined轉為數值時為NaN

     

 

 

判斷等號也放在Number里面特殊說明

== 抽象相等比較與+運算符不同,不再是String優先,而是Nuber優先。下面列舉x == y的例子

  • 如果x,y均為number,直接比較沒什么可解釋的了

    1 == 2 //false
  • 如果存在對象,ToPrimitive() type為number進行轉換,再進行后面比較

    var obj1 = {
        valueOf:function(){
            return'1'
        }
    }
    1 == obj1  //true
    //obj1轉為原始值,調用obj1.valueOf()
    //返回原始值'1'
    //'1'toNumber得到 1 然后比較 1 == 1
    [] == ![] //true
    //[]作為對象ToPrimitive得到 ''
    //![]作為boolean轉換得到0
    //'' == 0
    //轉換為 0==0 //true
  • 在boolean,按照ToNumber將boolean轉換為1或者0,再進行后面比較

    // boolean 先轉成number,按照上面的規則得到1
    // 3 == 1 false
    // 0 == 0 true
    3 == true    // false
    '0' == false //true
  • 如果x為string,y為number,x轉成number進行比較

    // '0' toNumber()得到 0
    // 0 == 0 true
    '0' == 0  // true
    

     

 

什么時候進行布爾轉換

  • 布爾比較時

  • if(obj) , while(obj) 等判斷時或者 三元運算符只能夠包含布爾值

條件部分的每個值都相當於false,使用否定運算符后,就變成了true

if ( !undefined
  && !null
  && !0
  && !NaN
  && !''
) {
  console.log('true');
} // true
​
//下面兩種情況也會轉成布爾類型
expression ? true : false
!! expression

 

 

NaN相關總結

NaN的概念

NaN 是一個全局對象的屬性,NaN 是一個全局對象的屬性,NaN是一種特殊的Number類型

什么時候返回NaN (開篇第二道題也得到解決)

  • 無窮大除以無窮大

  • 給任意負數做開方運算

  • 算數運算符與不是數字或無法轉換為數字的操作數一起使用

  • 字符串解析成數字

一些例子

Infinity/ Infinity;   // 無窮大除以無窮大
Math.sqrt(-1);         // 給任意負數做開方運算
'a' - 1;               // 算數運算符與不是數字或無法轉換為數字的操作數一起使用
'a' * 1;
'a' /1;
parseInt('a');         // 字符串解析成數字
parseFloat('a');
​
Number('a');   //NaN
'abc' - 1// NaN
undefined + 1// NaN
//一元運算符(注意點)
+'abc'// NaN
-'abc'// NaN

 

 

誤區

toString和String的區別

 

  • toString()可以將數據都轉為字符串,但是null和undefined不可以轉換

    console.log(null.toString())
    //報錯 TypeError: Cannot read property 'toString' of null

    console.log(undefined.toString())
    //報錯 TypeError: Cannot read property 'toString' of undefined
  • String

    String()可以將null和undefined轉換為字符串,但是沒法轉進制字符串

    console.log(String(null));
    // null
    console.log(String(undefined));
    // undefine
  • toString()括號中可以寫數字,代表進制

    • 二進制:.toString(2)

    • 八進制:.toString(8)

    • 十進制:.toString(10)

    • 十六進制:.toString(16)

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM