Javascript基礎之-強制型別轉換(一)

消磁123發表於2019-01-10

轉換為字串規則如下圖程式碼:

console.log(String(undefined));  // "undefined"
console.log(String(null));     // "null"
console.log(String(true));    // "true"
console.log(String(+0));      // "0"
console.log(String(-0));    // "0"
console.log(String(-20));   // "-20"
console.log(String(Infinity));  // "Infinity"
console.log(String(new Number(123)))    // 123
console.log(String(new Object()))    // [object Object]
console.log(100000000000000000000000000000);   // 1e+29

大致就是普通其他基本型別轉為字串的話,就直接轉為其值的字串表達形式,

如果是基本型別的封裝物件,會先拆封,然後再轉為字串,

如果是普通物件,則會呼叫其內部[class]的值,

如果是極大數和級小數,將會進行一些轉化,具體規則請參考ecma 官方文件https://www.ecma-internationa…

請思考下面的程式碼

var obj = {
  toString() {
    return "toString";
  }
}
console.log(String(obj))   // toString
var obj1 = Object.create(null);
obj1.valueOf = function() {
  return "valueOf";
}
console.log(String(obj1)); // valueOf

上面這個程式碼似乎可以看出,實際上普通物件轉為字串的過程,似乎就是toString()的一個過程,也就是呼叫其內部toString()的一個過程

如果toString()沒有咋辦,呼叫valueOf,如果這個也沒有呢,就直接報錯了。

轉換為數字的規則

普通轉換為數字的規則如下:

console.log(Number(true));  // 1
console.log(Number(0b1101))   // 13
console.log(Number(false));  // 0
console.log(Number("123"));  //123
console.log(Number("123a"));  //NaN
console.log(Number(undefined));  // NaN
console.log(Number(null));   // 0

不過呢,如果是物件型別的咋辦呢,實際上同上的一點是,如果是基本型別封裝後的物件,會先拆封,也就是轉為基本型別值,然後再轉為數字,比如說

console.log(Number(new String("123123")));   // 123123
console.log(Number([1]));   // 1
console.log(Number([1, 3]));   // NaN

可能你會疑惑,說,為啥陣列只有一個資料的時候可以轉換,有兩個資料的時候就是NaN了呢,原因在這裡,看程式碼

console.log([1].valueOf());  // [1]
console.log([1, 3].valueOf());   // [1, 3]
console.log([1].toString());  // 1
console.log([1, 3].toString());   //1, 3

可以看到,valueOf沒有返回基本型別值,所以轉而使用toString轉為基本型別值,這倆字串再轉為數字的結果就一目瞭然了,和上面的是一樣的

那麼轉為數字的過程中,valueOf和toString是哪個先執行的呢?

看程式碼

var a = {
  valueOf() {
    return 2;
  },
  toString() {
    return 3;
  }
}
var b = {
  valueOf() {
    return [1, 3];
  },
  toString() {
    return 3;
  }
}
var c = {
  toString() {
    return 3;
  }
}
var d = Object.create(null);
console.log(Number(a));  // 2
console.log(Number(b));  // 3
console.log(Number(c));  // 3
console.log(Number(d));  // Uncaught TypeError: Cannot convert object to primitive value

這個其實就說明了一個問題,就是說物件轉數字的時候,會先找valueOf(),如果valueOf()沒有,或者是說轉的是非基本資料型別的,將會使用toString(),最後基本型別專成數字型別的,如果valueOf和toString()都沒有,就直接報錯了

轉化為數字呢,除了以上使用Number(),還可以使用+符號,這個也可以實現從其他型別轉換到字串

console.log(+"abc");  // NaN
console.log(+"1111");  //1111
console.log(+[1]);  // 1
var obj = {
  valueOf() {
    return "1111";
  }
}
console.log(+obj);   // 1111

如果原資料型別是Date,那麼可以用Number或者+轉為以微秒為單位的unix時間戳

var d = new Date( "Mon, 18 Aug 2014 08:53:06 CDT" );
console.log(+d);    // 1408369986000
console.log(Number(d));   //1408369986000

parseInt和Number()的區別:看例子

var a = "123abc";
console.log(+a);   // NaN
console.log(parseInt(a));  // 123
console.log(parseInt("abc123"));  // NaN

實際上,parseInt會從左往右進行解析,找到非字串的時候停止,如果一開始就不可轉為數字,那麼就返回NaN

parseInt其他一些坑點,這裡就不細說了,想看的,可以找《你不知道的Javascript》瞭解細節

// 0 ("0" 來自於 "0.000008")
console.log(parseInt( 0.000008 ));
// 8 ("8" 來自於 "8e-7")
console.log(parseInt( 0.0000008 )); 
// 250 ("fa" 來自於 "false")
console.log(parseInt( false, 16 ));
// 15 ("f" 來自於 "function..")
console.log(parseInt( parseInt, 16 )); 
console.log(parseInt( "0x10" )); // 16
console.log(parseInt( "103", 2 )); // 2

轉化為布林值

下面是假值列表,理論上說,除了以下內容以外的值都是true

console.log(Boolean(undefined));
console.log(Boolean(null));
console.log(Boolean(false));
console.log(Boolean(+0));
console.log(Boolean(-0));
console.log(Boolean(NaN));
console.log(Boolean(""));

這裡有一點需要說明,規範裡有提到,所有的物件都是true,所以這方面尤其需要注意的就是下面的例子了

console.log(Boolean(new Boolean(false)));  // true
console.log(Boolean(new String("")));  // true
console.log(Boolean(new Number(0)));  // true

返回的都是true,雖然他是對假值得封裝,但是他們是物件,是物件就返回true,所以用假值物件或者其他看起來像價值的字串來進行if判斷是不靠譜的

var bObj = new Boolean(false);
var a = [];
var d = {};
var e = function() {}
var f = "false";
var g = "0";
var h = "``";
if (a && d && e && f && g && h) {
  console.log(`all right`);  // all right
}

一般顯式的吧資料轉為布林型,除了使用Boolean()以外,還可以使用!!符號,也就是連著反轉兩次

console.log(!!undefined); // false
console.log(!!new Boolean(false)); // true

好了就到這裡了,這一次因為東西比較零散,準備了一陣子,希望大家有所收穫

參考書籍《你不知道的Javascript中卷》

本文轉載自http://www.lht.ren/article/5/


相關文章