JS的类型转换你真的搞懂了吗

582 阅读5分钟

前言

JavaScript是一种动态类型语言,这意味着在运行时可以自由地改变变量的数据类型。类型转换是JavaScript中非常重要的一部分,它允许开发者在不同数据类型之间进行转换。本文将详细介绍JavaScript中的类型转换,包括显示转换和隐式转换,并通过实例帮助大家理解。官方文档地址在这里(es5.github.io/#x15.5.1.1)

正文

显示转换

显示转换是指人为通过特定的函数或构造器将一个值转换为另一种类型。以下是一些基本的转换方法:

原始值转原始值

1.原始值转布尔 Boolean(xx)

将任何非空字符串、非零数值、非空对象等转换为true;而false0nullundefinedNaN等会被转换为false

    console.log(Boolean(1));       // true
    console.log(Boolean(0));       // false
    console.log(Boolean(-1));      // true
    console.log(Boolean(NaN));     // false
    console.log(Boolean('abc'));   // true
    console.log(Boolean(''));      // false
    console.log(Boolean(false));   // false
    console.log(Boolean(undefined));// false
    console.log(Boolean(null));    // false
2.原始值转数字 Number(xx)

字符串转换为数字时,如果字符串可以解析为数字,则转换为相应的数字,否则为NaN。其他类型的值会根据其特性转换。

console.log(Number('123'));    // 123
console.log(Number('hello'));  // NaN
console.log(Number(true));     // 1
console.log(Number(false));    // 0
console.log(Number(''));       // 0
console.log(Number(' '));      // 0
console.log(Number(undefined));// NaN
console.log(Number(null));     // 0
3.原始值转字符串 String(xx)

将任意类型的值转换为其字符串表示形式。

console.log(String(123));      // "123"
console.log(String(true));     // "true"
console.log(String(false));    // "false"
console.log(String(undefined));// "undefined"
console.log(String(null));     // "null"
4.原始值转对象 new xxx()

这里提到的new Xxx()通常是通过构造函数创建一个新对象。例如,new String()new Number()new Boolean()等,这些是创建包装对象的方式,而不是直接转换原始值。

let a = '123';
console.log(new String(a));    // String { '123' }

let b = 123
console.log(new Number(b));    // Number { 123 }

重点:隐式转换

隐式转换是在js执行某些操作时自动发生的转换,比如在比较运算符使用等场景下(对象原始值通常发生隐式转换)。

提前要知道的知识

下面是js在进行隐式转换时会用的方法。

1.所有对象转原始值都会调用toString()

  • 对象:{}.toString() 得到由"[object 和 class 和 ]"组成的字符串

  • 数组:[].toString() 返回由数组内部元素以逗号拼接的字符串

  • 其它:xx.toString() 返回字符串字面量

  console.log({}.toString());    // "[object Object]"
  
  let map = new Map();
  console.log(map.toString());   // "[object Map]"
  
  let set = new Set();
  console.log(set.toString());   // "[object Set]"
  
  console.log([].toString());    //''
  console.log([123].toString());   //'1,2,3'
  
  function myFunction() { return 'Hello'; }
  console.log(myFunc.toString());        // "function myFunction() { return 'Hello'; }"
  
  console.log((new Date()).toString());  // "Wed Sep 11 2024 00:14:53 GMT+0800 (中国标准时间)"
  
  let numObj = new Number(123);
  console.log(numObj.toString()); // "123"

2.valueOf() 可以将对象转成原始类型

对于包装类对象,valueOf方法会返回对象包装的原始值。

let numObj = new Number(123);
console.log(numObj.valueOf()); // 123

let strObj = new String('hello');
console.log(strObj.valueOf()); // "hello"

3.对象转布尔,一定是true

4.ToPrimitive()抽象操作(重点)

ToPrimitive是一个抽象操作,用于将一个对象转换为原始值。

1.ToPrimitive(obj, String)

  • 如果接收到的是原始值,直接返回值
  • 否则,调用toString 方法,如何得到原始值,返回
  • 否则,调用valueof 方法,如何得到原始值,返回
  • 报错

2.ToPrimitive(obj, Number)

  • 如果接收到的是原始值,直接返回值
  • 否则,调用valueOf 方法,如何得到原始值,返回
  • 否则,调用toString 方法,如何得到原始值,返回
  • 报错

发生隐式转换的情况和例子(有详细转换过程)

  • js面对原始类型时会使用ToNumberToString,将原始值转换为数字,字符串类型。
  • js面对对象会时使用ToPrimitive()转为原始类型,如果还需操作达到目标就使用上面几个方法进行操作转换为相应类型,但是呢,对象转布尔,一定是true,所以ToBoolean()可以处理对象和原始值。
一元操作符 +

一元操作符+通常用于将一个值转换为数字,如果值不能被转换为数字,则结果为NaN

  1. 如果操作数已经是原始值(如数字、字符串或布尔值)

    • js会使用 ToNumber 方法(这个方法会将该原始值转换为数字)。
  2. 如果操作数是对象

    • 首先调用 ToPrimitive(obj, Number) 抽象操作来获取该对象的一个原始值表示。
    • ToPrimitive 返回的原始值随后会被传递给 ToNumber 方法进行数字转换。
console.log(+true);             // 1
// +true  ==> 1
// ToNumber(true)
// 1

console.log(+false);            // 0

console.log(+'123');            // 123
// +'123'  ==> 123
// ToNumber('123')
// 123


// +[]  ==> 0
// ToPrimitive([], Number)
// [].valueOf() 
// [].toString()   ===> ''
// ToNumber('')
// 0
二元操作符 +

当使用加法运算符+时,如果其中一个操作数是字符串,则另一个也会被转换为字符串,然后进行字符串拼接;否则,将两个操作数转换为数字后相加。

console.log(1 + '1');           // "11"
// 1 + '1' ==> '11'
// ToString(1) + '1'
// '1' + '1'`
// '11'

console.log(1 + 2);             // 3

console.log(null + 1)           // 1
// null + 1 ==> 1
// ToNumber(null) + 1
// 0 + 1
// 1

console.log({} + '1')            // '[object Object]1'
// ToPrimitive({} ,string) + '1'
// {}.toString() + '1'
// '[object Object]' + '1'
// '[object Object]1'

console.log([] + {})            // '[object Object]'
// ToPrimitive([],number)  + ToPrimitive({},number)
// [].valueOf() + {}.valueOf()==> [] + {}
// [].toString() + {}.toString()
// '' + '[object Object]'
// '[object Object]'
条件语句if

ToBoolean()可以处理对象和原始值,对象转布尔,一定是true

if ({}) {   // ToBoolean({})  ==> true
  console.log("{} is true");  // 输出 "{} is true''
}

if (0) {   //ToBoolean(0)  ==> false
  console.log("0 is true");
} else {
  console.log("0 is false");  // 输出 "0 is false"
}
等价性 ==

==操作符会尝试将两边的操作数转换为同一类型后再进行比较,,基本都是转换为数字类型,如果==两边有出现!先将含有!的一边转换为布尔类型。

console.log(1=={})   // false
// 1 == {}
// 1 == ToPrimitive({})
// 1 == '[object Object]'
// 1 == NaN


console.log([]==![])   // true
//[] == ![]   // 对象转布尔,一定是`true`
// [] == false 
// [] == 0
// ToPrimitive([],number) == 0
// '' == 0
// 0 == 0

===是需要类型都相同的,是不会发生隐式转换的。

总结

通过以上的讲实例,希望大家对JavaScript中的类型转换技巧有了更深的了解,感谢大家的阅读!

image.png