溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

JavaScript的數(shù)據(jù)類型你了解多少

發(fā)布時間:2021-09-30 10:46:20 來源:億速云 閱讀:126 作者:柒染 欄目:web開發(fā)

JavaScript的數(shù)據(jù)類型你了解多少,很多新手對此不是很清楚,為了幫助大家解決這個難題,下面小編將為大家詳細(xì)講解,有這方面需求的人可以來學(xué)習(xí)下,希望你能有所收獲。

 前言

作為JavaScript的入門知識點,Js數(shù)據(jù)類型在整個JavaScript的學(xué)習(xí)過程中其實尤為重要。最常見的是邊界數(shù)據(jù)類型條件判斷問題。

概念

undefined、Null、Boolean、String、Number、Symbol、BigInt為基礎(chǔ)類型;

Object為引用類型,其中包括Array、RegExp、Date、Math、Function這幾種常見的類型。

JavaScript的數(shù)據(jù)類型你了解多少

數(shù)據(jù)類型大致分為兩類來進(jìn)行存儲。

基礎(chǔ)類型存儲在棧內(nèi)存,被引用或拷貝時,會創(chuàng)建一個完全相等的變量。

引用類型存儲在堆內(nèi)存,存儲的是地址,多個引用指向同一個地址,這里會涉及一個“共享”的概念。

JavaScript的數(shù)據(jù)類型你了解多少

示例題一:

let a = {  name:"maomin",   age:"20" } let b = a; console.log(a.name); // "maomin" b.name = "haojie"; console.log(a.name); // "haojie" console.log(b.name); // "haojie"

這里就體現(xiàn)了引用類型的“共享”的特性,即這兩個值都存在同一塊內(nèi)存中共享,一個發(fā)生了改變,另外一個也隨之跟著變化。

示例題二:

let a = {    name: 'maomin',    age: 20  }  function change(o) {    o.age = 24;    o = {      name: 'haojie',      age: 30    }    return o;  }  let b = change(a);  console.log(b.age);    // 30  console.log(a.age);    // 24

函數(shù)傳參進(jìn)來的 o,傳遞的是對象在堆中的內(nèi)存地址值,通過調(diào)用 o.age = 24確實改變了 a 對象的 age  屬性;但是代碼中{name:'haojie',age:30}卻又把 o 變成了另一個內(nèi)存地址,將{name: 'haojie', age:  30}存入其中,最后返回 b 的值就變成了 {name: 'haojie', age: 30}。

其實,上面兩個例子很顯明地闡述了在Vue.js組件中data屬性必須是一個函數(shù)而不是一個對象,每個實例可以維護(hù)一份被返回對象的獨立的拷貝。

數(shù)據(jù)類型檢測

第一種檢測方法:typeof

typeof 1 // 'number'  typeof '1' // 'string'  typeof undefined // 'undefined'  typeof true // 'boolean'  typeof Symbol() // 'symbol'  typeof null // 'object'  typeof [] // 'object'  typeof {} // 'object'  typeof console // 'object'  typeof console.log // 'function'

可以看到,前 6 個都是基礎(chǔ)數(shù)據(jù)類型,而為什么第 6 個 null 的typeof是 object 呢?這里要和你強(qiáng)調(diào)一下,雖然 typeof  null會輸出 object,但這只是 JS 存在的一個悠久 Bug,不代表 null 就是引用數(shù)據(jù)類型,并且 null 本身也不是對象。因此,null 在  typeof 之后返回的是有問題的結(jié)果,不能作為判斷 null 的方法。如果你需要在 if 語句中判斷是否為null,直接通過  ===null來判斷就好。

此外還要注意,引用數(shù)據(jù)類型 Object,用 typeof 來判斷的話,除了 function 會正確判斷以外,其余都是  object,是無法判斷出來的。

第二種檢測方法:instanceof

我們 new 一個對象,那么這個新對象就是它原型鏈繼承上面的對象了,通過  instanceof我們能判斷這個對象是否是之前那個構(gòu)造函數(shù)生成的對象,這樣就基本可以判斷出這個新對象的數(shù)據(jù)類型。

let Car = function() {}  let benz = new Car();  benz instanceof Car; // true   let car = new String('maomin');  car instanceof String; // true   let str = 'haojie';  str instanceof String; // false

我們自己可以實現(xiàn)一個 instanceof 的底層實現(xiàn):

function myInstanceof(target, typeObj) {    // 這里先用typeof來判斷基礎(chǔ)數(shù)據(jù)類型,如果是,直接返回false    if(typeof target !== 'object' || target === null) return false;    // getProtypeOf是Object對象自帶的API,能夠拿到參數(shù)的原型對象    let proto = Object.getPrototypeOf(target);    while(true) {                  //循環(huán)往下尋找,直到找到相同的原型對象      if(proto === null) return false;      if(proto === typeObj.prototype) return true;//找到相同原型對象,返回true      proto = Object.getPrototypeof(proto);      }  }  // 驗證一下自己實現(xiàn)的myInstanceof  console.log(myInstanceof(new String('maomin'), String));    // true  console.log(myInstanceof('maomin', String));                // false

看到上述代碼的實現(xiàn),我們會總結(jié)這兩個方法的差異性:

  1. 鴻蒙官方戰(zhàn)略合作共建——HarmonyOS技術(shù)社區(qū)

  2. instanceof可以準(zhǔn)確地判斷復(fù)雜引用數(shù)據(jù)類型,但是不能正確判斷基礎(chǔ)數(shù)據(jù)類型;

  3. typeof 也存在弊端,它雖然可以判斷基礎(chǔ)數(shù)據(jù)類型(null 除外),但是引用數(shù)據(jù)類型中,除了 function 類型以外,其他的也無法判斷。

第三種檢測方法:Object.prototype.toString

toString() 是 Object 的原型方法,調(diào)用該方法,可以統(tǒng)一返回格式為 “[object Xxx]” 的字符串,其中  Xxx就是對象的類型,第一個首字母要大寫。對于 Object 對象,直接調(diào)用 toString()就能返回"[object  Object]";而對于其他對象,則需要通過call來調(diào)用,才能返回正確的類型信息。

Object.prototype.toString({})       // "[object Object]"  Object.prototype.toString.call({})  // 同上結(jié)果,加上call也ok  Object.prototype.toString.call(1)    // "[object Number]"  Object.prototype.toString.call('1')  // "[object String]"  Object.prototype.toString.call(true)  // "[object Boolean]"  Object.prototype.toString.call(function(){})  // "[object Function]"  Object.prototype.toString.call(null)   //"[object Null]"  Object.prototype.toString.call(undefined) //"[object Undefined]"  Object.prototype.toString.call(/123/g)    //"[object RegExp]"  Object.prototype.toString.call(new Date()) //"[object Date]"  Object.prototype.toString.call([])       //"[object Array]"  Object.prototype.toString.call(document)  //"[object HTMLDocument]"  Object.prototype.toString.call(window)   //"[object Window]"

好,下面我們將實現(xiàn)一個完善的數(shù)據(jù)類型檢測方法。

function getType(obj){    let type  = typeof obj;    if (type !== "object") {    // 先進(jìn)行typeof判斷,如果是基礎(chǔ)數(shù)據(jù)類型,直接返回      return type;    }    // 對于typeof返回結(jié)果是object的,再進(jìn)行如下的判斷,正則返回結(jié)果    return Object.prototype.toString.call(obj).replace(/^\[object (\S+)\]$/, '$1');  // 注意正則中間有個空格  }  /* 代碼驗證,需要注意大小寫,哪些是typeof判斷,哪些是toString判斷?思考下 */  getType([])     // "Array" typeof []是object,因此toString返回  getType('123')  // "string" typeof 直接返回  getType(window) // "Window" toString返回  getType(null)   // "Null"首字母大寫,typeof null是object,需toString來判斷  getType(undefined)   // "undefined" typeof 直接返回  getType()            // "undefined" typeof 直接返回  getType(function(){}) // "function" typeof能判斷,因此首字母小寫  getType(/123/g)      //"RegExp" toString返回

數(shù)據(jù)類型轉(zhuǎn)換

在日常的業(yè)務(wù)開發(fā)中,經(jīng)常會遇到 JavaScript 數(shù)據(jù)類型轉(zhuǎn)換問題,有的時候需要我們主動進(jìn)行強(qiáng)制轉(zhuǎn)換,而有的時候 JavaScript  會進(jìn)行隱式轉(zhuǎn)換,隱式轉(zhuǎn)換的時候就需要我們多加留心。

'123' == 123   // true  '' == null    // false  '' == 0        // true  [] == 0        // true  [] == ''       // true  [] == ![]      // true  null == undefined //  true  Number(null)     // 0  Number('')      // 0  parseInt('');    // NaN  {}+10           // 10  let obj = {      [Symbol.toPrimitive]() {          return 200;      },      valueOf() {          return 300;      },      toString() {          return 'Hello';      }  }  console.log(obj + 200); // 400

上面的代碼相信你并不陌生,基本涵蓋了我們平常容易疏漏的一些情況,這就是在做數(shù)據(jù)類型轉(zhuǎn)換時經(jīng)常會遇到的強(qiáng)制轉(zhuǎn)換和隱式轉(zhuǎn)換的方式,

強(qiáng)制類型轉(zhuǎn)換

強(qiáng)制類型轉(zhuǎn)換方式包括Number()、parseInt()、parseFloat()、toString()、String()、Boolean(),這幾種方法都比較類似,通過字面意思可以很容易理解,都是通過自身的方法來進(jìn)行數(shù)據(jù)類型的強(qiáng)制轉(zhuǎn)換。

Number() 方法的強(qiáng)制轉(zhuǎn)換規(guī)則

  • 如果是布爾值,true 和 false 分別被轉(zhuǎn)換為 1 和 0;

  • 如果是數(shù)字,返回自身;

  • 如果是 null,返回0;

  • 如果是 undefined,返回 NaN;

  • 如果是字符串,遵循以下規(guī)則:如果字符串中只包含數(shù)字(或者是 0X / 0x  開頭的十六進(jìn)制數(shù)字字符串,允許包含正負(fù)號),則將其轉(zhuǎn)換為十進(jìn)制;如果字符串中包含有效的浮點格式,將其轉(zhuǎn)換為浮點數(shù)值;如果是空字符串,將其轉(zhuǎn)換為  0;如果不是以上格式的字符串,均返回 NaN;

  • 如果是 Symbol,拋出錯誤;

  • 如果是對象,并且部署了 [Symbol.toPrimitive],那么調(diào)用此方法,否則調(diào)用對象的  valueOf()方法,然后依據(jù)前面的規(guī)則轉(zhuǎn)換返回的值;如果轉(zhuǎn)換的結(jié)果是 NaN ,則調(diào)用對象的  toString()方法,再次依照前面的順序轉(zhuǎn)換返回對應(yīng)的值。

Number(true);        // 1  Number(false);       // 0  Number('0111');      //111  Number(null);        //0  Number('');          //0  Number('1a');        //NaN  Number(-0X11);       //-17  Number('0X11')       //17

其中,上面分別列舉了比較常見的 Number  轉(zhuǎn)換的例子,它們都會把對應(yīng)的非數(shù)字類型轉(zhuǎn)換成數(shù)字類型,而有一些實在無法轉(zhuǎn)換成數(shù)字的,最后只能輸出NaN的結(jié)果。

parseInt() 方法的強(qiáng)制轉(zhuǎn)換規(guī)則

考慮到用 Number()函數(shù)轉(zhuǎn)換字符串時相對復(fù)雜且有點反常規(guī),通常在需要得到整數(shù)時可以優(yōu)先使用  parseInt()函數(shù)。parseInt()函數(shù)更專注于字符串是否包含數(shù)值模式。字符串最前面的空格會被忽略,從第一個非空格字符開始轉(zhuǎn)換。如果第一個字符不是數(shù)值字符、加號或減號,parseInt()立即返回  NaN。這意味著空字符串也會返回 NaN(這一點跟 Number()不一樣,它返回  0)。如果第一個字符是數(shù)值字符、加號或減號,則繼續(xù)依次檢測每個字符,直到字符串末尾,或碰到非數(shù)值字符。比如,"1234blue"會被轉(zhuǎn)換為  1234,因為"blue"會被完全忽略。類似地,"22.5"會被轉(zhuǎn)換為22,因為小數(shù)點不是有效的整數(shù)字符。

假設(shè)字符串中的第一個字符是數(shù)值字符,parseInt()函數(shù)也能識別不同的整數(shù)格式(十進(jìn)制、八進(jìn)制、十六進(jìn)制)。換句話說,如果字符串以"0x"開頭,就會被解釋為十六進(jìn)制整數(shù)。如果字符串以"0"開頭,且緊跟著數(shù)值字符,在非嚴(yán)格模式下會被某些實現(xiàn)解釋為八進(jìn)制整數(shù)。

let num1 = parseInt("1234blue"); // 1234  let num2 = parseInt(""); // NaN  let num3 = parseInt("0xA"); // 10,解釋為十六進(jìn)制整數(shù) let num4 = parseInt(22.5); // 22  let num5 = parseInt("70"); // 70,解釋為十進(jìn)制值 let num6 = parseInt("0xf"); // 15,解釋為十六進(jìn)制整數(shù)

不同的數(shù)值格式很容易混淆,因此 parseInt()也接收第二個參數(shù),用于指定底數(shù)(進(jìn)制數(shù))。如果知道要解析的值是十六進(jìn)制,那么可以傳入 16  作為第二個參數(shù),以便正確解析:

let num = parseInt("0xAF", 16); // 175

事實上,如果提供了十六進(jìn)制參數(shù),那么字符串前面的"0x"可以省掉:

let num1 = parseInt("AF", 16); // 175  let num2 = parseInt("AF"); // NaN

在這個例子中,第一個轉(zhuǎn)換是正確的,而第二個轉(zhuǎn)換失敗了。區(qū)別在于第一次傳入了進(jìn)制數(shù)作為參數(shù),告訴  parseInt()要解析的是一個十六進(jìn)制字符串。而第二個轉(zhuǎn)換檢測到第一個字符就是非數(shù)值字符,隨即自動停止并返回 NaN。

通過第二個參數(shù),可以極大擴(kuò)展轉(zhuǎn)換后獲得的結(jié)果類型。比如:

let num1 = parseInt("10", 2); // 2,按二進(jìn)制解析  let num2 = parseInt("10", 8); // 8,按八進(jìn)制解析  let num3 = parseInt("10", 10); // 10,按十進(jìn)制解析  let num4 = parseInt("10", 16); // 16,按十六進(jìn)制解析

因為不傳底數(shù)參數(shù)相當(dāng)于讓  parseInt()自己決定如何解析,所以為避免解析出錯,建議始終傳給它第二個參數(shù)。多數(shù)情況下解析的應(yīng)該都是十進(jìn)制數(shù),此時第二個參數(shù)就要傳入 10。

parseFloat() 方法的強(qiáng)制轉(zhuǎn)換規(guī)則

parseFloat()函數(shù)的工作方式跟parseInt()函數(shù)類似,都是從位置 0  開始檢測每個字符。同樣,它也是解析到字符串末尾或者解析到一個無效的浮點數(shù)值字符為止。這意味著第一次出現(xiàn)的小數(shù)點是有效的,但第二次出現(xiàn)的小數(shù)點就無效了,此時字符串的剩余字符都會被忽略。因此,"22.34.5"將轉(zhuǎn)換成  22.34。

parseFloat()函數(shù)的另一個不同之處在于,它始終忽略字符串開頭的零。十六進(jìn)制數(shù)值始終會返回  0。因為parseFloat()只解析十進(jìn)制值,因此不能指定底數(shù)。最后,如果字符串表示整數(shù)(沒有小數(shù)點或者小數(shù)點后面只有一個零),則  parseFloat()返回整數(shù)。下面是幾個示例:

let a = parseFloat(true); // NaN  let num1 = parseFloat("1234blue"); // 1234,按整數(shù)解析  let num2 = parseFloat("0xA"); // 0   let num3 = parseFloat("22.5"); // 22.5   let num4 = parseFloat("22.34.5"); // 22.34   let num5 = parseFloat("0908.5"); // 908.5   let num6 = parseFloat("3.125e7"); // 31250000

Boolean() 方法的強(qiáng)制轉(zhuǎn)換規(guī)則

除了undefined、null、 false、 ''、0(包括 +0,-0)、NaN轉(zhuǎn)換出來是false,其他都是 true。

Boolean(0)          //false  Boolean(null)       //false  Boolean(undefined)  //false  Boolean(NaN)        //false  Boolean(1)          //true  Boolean(13)         //true  Boolean('12')       //true

toString() 方法的強(qiáng)制轉(zhuǎn)換規(guī)則

這個方法唯一的用途就是返回當(dāng)前值的字符串等價物。比如:

let age = 11;   let ageAsString = age.toString(); // 字符串"11"   let found = true;   let foundAsString = found.toString(); // 字符串"true"

toString()方法可見于數(shù)值、布爾值、對象和字符串值。(沒錯,字符串值也有 toString()方法,該方法只是簡單地返回自身的一個副本。)null  和 undefined值沒有toString()方法。

多數(shù)情況下,toString()不接收任何參數(shù)。不過,在對數(shù)值調(diào)用這個方法時,toString()可以接收一個底數(shù)參數(shù),即以什么底數(shù)來輸出數(shù)值的字符串表示。默認(rèn)情況下,toString()返回數(shù)值的十

進(jìn)制字符串表示。而通過傳入?yún)?shù),可以得到數(shù)值的二進(jìn)制、八進(jìn)制、十六進(jìn)制,或者其他任何有效基

數(shù)的字符串表示,比如:

let num = 10;   console.log(num.toString()); // "10"   console.log(num.toString(2)); // "1010"   console.log(num.toString(8)); // "12"   console.log(num.toString(10)); // "10"   console.log(num.toString(16)); // "a"

這個例子展示了傳入底數(shù)參數(shù)時,toString()輸出的字符串值也會隨之改變。數(shù)值 10 可以輸出為

任意數(shù)值格式。注意,默認(rèn)情況下(不傳參數(shù))的輸出與傳入?yún)?shù) 10 得到的結(jié)果相同。

String() 方法的強(qiáng)制轉(zhuǎn)換規(guī)則

如果你不確定一個值是不是 null 或 undefined,可以使用  String()轉(zhuǎn)型函數(shù),它始終會返回表示相應(yīng)類型值的字符串。String()函數(shù)遵循如下規(guī)則。

  • 如果值有toString()方法,則調(diào)用該方法(不傳參數(shù))并返回結(jié)果。

  • 如果值是null,返回"null"。

  • 如果值是 undefined,返回"undefined"。

下面看幾個例子:

let value1 = 10;   let value2 = true;   let value3 = null;   let value4;   console.log(String(value1)); // "10"   console.log(String(value2)); // "true"   console.log(String(value3)); // "null"   console.log(String(value4)); // "undefined"

這里展示了將 4 個值轉(zhuǎn)換為字符串的情況:一個數(shù)值、一個布爾值、一個 null 和一個  undefined。數(shù)值和布爾值的轉(zhuǎn)換結(jié)果與調(diào)用toString()相同。因為 null 和 undefined沒有 toString()方法,所以  String()方法就直接返回了這兩個值的字面量文本。

  • 用加號操作符給一個值加上一個空字符串""也可以將其轉(zhuǎn)換為字符串。

隱式類型轉(zhuǎn)換

凡是通過邏輯運(yùn)算符 (&&、 ||、!)、運(yùn)算符 (+、-、*、/)、關(guān)系操作符 (>、 <、 <=  、>=)、相等運(yùn)算符 (==) 或者 if/while 條件的操作,如果遇到兩個數(shù)據(jù)類型不一樣的情況,都會出現(xiàn)隱式類型轉(zhuǎn)換。

下面主要說一下日常用得比較多的“==”和“+”這兩個符號的隱式轉(zhuǎn)換規(guī)則。

'==' 的隱式類型轉(zhuǎn)換規(guī)則

  • 如果類型相同,無須進(jìn)行類型轉(zhuǎn)換;

  • 如果其中一個操作值是 null或者 undefined,那么另一個操作符必須為null或者  undefined,才會返回true,否則都返回false;

  • 如果其中一個是 Symbol類型,那么返回false;

  • 兩個操作值如果為string 和 number類型,那么就會將字符串轉(zhuǎn)換為 number;

  • 如果一個操作值是boolean,那么轉(zhuǎn)換成 number;

  • 如果一個操作值為 object 且另一方為 string、number 或者 symbol,就會把 object 轉(zhuǎn)為原始類型再進(jìn)行判斷(調(diào)用  object 的 valueOf/toString方法進(jìn)行轉(zhuǎn)換)。

null == undefined       // true  規(guī)則2  null == 0               // false 規(guī)則2  '' == null              // false 規(guī)則2  '' == 0                 // true  規(guī)則4 字符串轉(zhuǎn)隱式轉(zhuǎn)換成Number之后再對比  '123' == 123            // true  規(guī)則4 字符串轉(zhuǎn)隱式轉(zhuǎn)換成Number之后再對比  0 == false              // true  e規(guī)則 布爾型隱式轉(zhuǎn)換成Number之后再對比  1 == true               // true  e規(guī)則 布爾型隱式轉(zhuǎn)換成Number之后再對比  var a = {    value: 0,    valueOf: function() {      this.value++;      return this.value;    }  };  // 注意這里a又可以等于1、2、3  console.log(a == 1 && a == 2 && a ==3);  //true f規(guī)則 Object隱式轉(zhuǎn)換  // 注:但是執(zhí)行過3遍之后,再重新執(zhí)行a==3或之前的數(shù)字就是false,因為value已經(jīng)加上去了,這里需要注意一下

'+' 的隱式類型轉(zhuǎn)換規(guī)則

'+' 號操作符,不僅可以用作數(shù)字相加,還可以用作字符串拼接。僅當(dāng)  '+'號兩邊都是數(shù)字時,進(jìn)行的是加法運(yùn)算;如果兩邊都是字符串,則直接拼接,無須進(jìn)行隱式類型轉(zhuǎn)換。

除了上述比較常規(guī)的情況外,還有一些特殊的規(guī)則,如下所示。

  • 如果其中有一個是字符串,另外一個是 undefined、null或布爾型,則調(diào)用 toString()  方法進(jìn)行字符串拼接;如果是純對象、數(shù)組、正則等,則默認(rèn)調(diào)用對象的轉(zhuǎn)換方法會存在優(yōu)先級,然后再進(jìn)行拼接。

  • 如果其中有一個是數(shù)字,另外一個是undefined、null、布爾型或數(shù)字,則會將其轉(zhuǎn)換成數(shù)字進(jìn)行加法運(yùn)算,對象的情況還是參考上一條規(guī)則。

  • 如果其中一個是字符串、一個是數(shù)字,則按照字符串規(guī)則進(jìn)行拼接。

1 + 2        // 3  常規(guī)情況  '1' + '2'    // '12' 常規(guī)情況  // 下面看一下特殊情況  '1' + undefined   // "1undefined" 規(guī)則1,undefined轉(zhuǎn)換字符串  '1' + null        // "1null" 規(guī)則1,null轉(zhuǎn)換字符串  '1' + true        // "1true" 規(guī)則1,true轉(zhuǎn)換字符串  '1' + 1n          // '11' 比較特殊字符串和BigInt相加,BigInt轉(zhuǎn)換為字符串  1 + undefined     // NaN  規(guī)則2,undefined轉(zhuǎn)換數(shù)字相加NaN  1 + null          // 1    規(guī)則2,null轉(zhuǎn)換為0  1 + true          // 2    規(guī)則2,true轉(zhuǎn)換為1,二者相加為2  1 + 1n            // 錯誤  不能把BigInt和Number類型直接混合相加  '1' + 3           // '13' 規(guī)則3,字符串拼接

整體來看,如果數(shù)據(jù)中有字符串,JavaScript  類型轉(zhuǎn)換還是更傾向于轉(zhuǎn)換成字符串,因為第三條規(guī)則中可以看到,在字符串和數(shù)字相加的過程中最后返回的還是字符串,這里需要關(guān)注一下。

Object 的轉(zhuǎn)換規(guī)則

對象轉(zhuǎn)換的規(guī)則,會先調(diào)用內(nèi)置的[ToPrimitive]函數(shù),其規(guī)則邏輯如下:

  • 如果部署了 Symbol.toPrimitive方法,優(yōu)先調(diào)用再返回;

  • 調(diào)用valueOf(),如果轉(zhuǎn)換為基礎(chǔ)類型,則返回;

  • 調(diào)用toString(),如果轉(zhuǎn)換為基礎(chǔ)類型,則返回;

  • 如果都沒有返回基礎(chǔ)類型,會報錯。

var obj = {    value: 1,    valueOf() {      return 2;    },    toString() {      return '3'    },    [Symbol.toPrimitive]() {      return 4    }  }  console.log(obj + 1); // 輸出5  // 因為有Symbol.toPrimitive,就優(yōu)先執(zhí)行這個;如果Symbol.toPrimitive這段代碼刪掉,則執(zhí)行valueOf打印結(jié)果為3;如果valueOf也去掉,則調(diào)用toString返回'31'(字符串拼接)  // 再看兩個特殊的case:  10 + {}  // "10[object Object]",注意:{}會默認(rèn)調(diào)用valueOf是{},不是基礎(chǔ)類型繼續(xù)轉(zhuǎn)換,調(diào)用toString,返回結(jié)果"[object Object]",于是和10進(jìn)行'+'運(yùn)算,按照字符串拼接規(guī)則來,參考'+'的規(guī)則C  [1,2,undefined,4,5] + 10  // "1,2,,4,510",注意[1,2,undefined,4,5]會默認(rèn)先調(diào)用valueOf結(jié)果還是這個數(shù)組,不是基礎(chǔ)數(shù)據(jù)類型繼續(xù)轉(zhuǎn)換,也還是調(diào)用toString,返回"1,2,,4,5",然后再和10進(jìn)行運(yùn)算,還是按照字符串拼接規(guī)則,參考'+'的第3條規(guī)則

1.**數(shù)據(jù)類型的基本概念:**這是必須掌握的知識點,作為深入理解 JavaScript 的基礎(chǔ)。

2.數(shù)據(jù)類型的判斷方法:typeof和instanceof,以及Object.prototype.toString 的判斷數(shù)據(jù)類型、手寫 instanceof  代碼片段,這些是日常開發(fā)中經(jīng)常會遇到的。

3.**數(shù)據(jù)類型的轉(zhuǎn)換方式:**兩種數(shù)據(jù)類型的轉(zhuǎn)換方式,日常寫代碼過程中隱式轉(zhuǎn)換需要多留意,如果理解不到位,很容易引起在編碼過程中的  bug,得到一些意想不到的結(jié)果。

看完上述內(nèi)容是否對您有幫助呢?如果還想對相關(guān)知識有進(jìn)一步的了解或閱讀更多相關(guān)文章,請關(guān)注億速云行業(yè)資訊頻道,感謝您對億速云的支持。

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI