jejuin / Blog

我的博客:记录、总结、分享前端知识
MIT License
4 stars 0 forks source link

ECMAScript 之数据类型转换(下) #20

Open jejuin opened 4 years ago

jejuin commented 4 years ago

前言

在上一篇 《ECMAScript 之数据类型转换(上)》中提到了数据类型转换分为两种:

本篇文章主要针对这两种类型转换进行介绍。

关联阅读

显示数据类型转换

ToPrimitive

对象类型可显示调用 toStringvalueOf 方法进行 ToPrimitive 转换。

对象类型的 toStringvalueOf 方法均继承于 Object.proptotype

var strObj= "1"; console.log(strObj.toString()) // "1"

var boolean= false; console.log(booleanObj.toString()) // "false"

var numObj= new Number(1); console.log(numObj.toString()) // "1"

- ` Object.proptotype.valueOf`:返回对象内部属性 [[Value]] 的值。大部分内置对象都覆写了该方法,返回各自的实现。
```js
var obj = new Object();
console.log(obj.valueOf()) // {}

var strObj= "1";
console.log(strObj.valueOf()) // 1

var boolean= false;
console.log(booleanObj.valueOf()) // false

var numObj= new Number(1);
console.log(numObj.valueOf()) // 1

ToBoolean

可显示调用 Boolean(input) 方法进行 ToBoolean 转换

ToNumber

可显示调用 Number(input)parseInt(string , radix)parseFloat(string) 方法进行 ToNumber 转换。parseInt(string , radix)parseFloat(string) 只能用于 StringToNumber, Number(input) 可接收任何类型参数进行转换。

parseInt(string, radix)

解析一个字符串并返回指定基数的十进制整数, radix 是2-36之间的整数,表示被解析字符串的基数。—— MDN

算法如下:

  1. Call ToString(string).
  2. 去除 Result(1) 字符串前面的所有空白
  3. 如果 radix 是 undefined、0或未指定的,JavaScript 会假定以下情况:
    • 如果输入的 string 以 "0x"或 "0x"开头,那么 radix 被假定为16,字符串的其余部分被当做十六进制数去解析。
    • 如果输入的 string 以 "0"开头, radix 被假定为 8(八进制)或 10(十进制)。具体选择哪一个 radix 取决于实现。ECMAScript 5 澄清了应该使用 10 (十进制),移除了八进制解析,但不是所有的浏览器都支持。因此,在使用 parseInt 时,一定要指定一个 radix。
    • 如果输入的 string 以任何其他值开头, radix 是 10 (十进制)。
  4. 如果 radix 小于 2 或大于 36,则返回 NaN
  5. 如果 string 不是指定 radix 参数中的数字,它将忽略该字符以及所有后续字符,并返回到该点为止已解析的整数值。
  6. parseInt 可以理解两个符号。+ 表示正数,- 表示负数。
  7. 如果第一个字符不能转换为数字,则会返回 NaN。
    
    parseInt("Hello", 8); // NaN
    parseInt("546", 2);   // NaN

// 以下例子均返回15 parseInt("0xF", 16); parseInt("F", 16); parseInt("17", 8); parseInt(021, 8); parseInt("015", 10); parseInt(15.99, 10); parseInt("15,123", 10); parseInt("FXX123", 16); parseInt("1111", 2); parseInt("15 * 3", 10); parseInt("15e2", 10); parseInt("15px", 10); parseInt("12 2 ", 13);

// 以下例子均返回 -15 parseInt("-F", 16); parseInt("-0F", 16); parseInt("-0XF", 16); parseInt(-15.1, 10); parseInt(" -17", 8); parseInt(" -15", 10); parseInt("-1111", 2); parseInt("-15e1", 10); parseInt("-12", 13);

// 下例中全部返回 4 parseInt(4.7, 10); parseInt(4.7 * 1e22, 10); // 非常大的数值变成 4 parseInt(0.00000000000434, 10); // 非常小的数值变成 4 => 0.00000000000434.toString() = "4.34e-12"

parseInt("0e0",16); // 224

> 示例来源 MDN

### parseFloat(string)
>parseFloat() 函数解析一个字符串参数并返回一个浮点数。—— MDN

算法如下:

1. Call ToString(string).
2. 去除 Result(1) 字符串前面的所有空白
3. 如果给定字符串值不能被转换成数值,则会返回 NaN。
4. 如果第一个字符不能转换为数字,则会返回 NaN。
6. 如果 parseFloat 在解析过程中遇到了正号(+)、负号(-)、数字(0-9)、小数点(.)、或者科学记数法中的指数(e 或 E)以外的字符,则它会忽略该字符以及之后的所有字符,返回当前已经解析到的浮点数。
7. 第二个小数点的出现也会使解析停止(在这之前的字符都会被解析)。

## ToString
可显示调用 `String(input)` 与 `toString()` 方法进行 ToString 转换

## ToObject
原始数据类型可自动装箱为对应的包装类型对象。

关联阅读:
- [ECMAScript 之原始数据类型包装对象](https://github.com/jejuin/Blog/issues/21)

# 隐式数据类型转换

## 一元运算符(+,-)
算法:
1. 对参数执行 ToNumber 操作
```js
console.log(+"123") // 123
console.log(+[]); // 0
console.log(+['1']); // 1
console.log(+['1', '2', '3']); // NaN
console.log(+{}); // NaN
console.log(-[]); // -0

二元运算符(+)

算法:

  1. 首先会执行 ToPrimitive 将两个参数转换为原始值
  2. 如果其中一个参数是字符串,则执行字符串拼接操作,返回 ToString(param1) + ToString(param2)。
  3. 否则将两个参数都转换为 Number,执行数学相加操作,返回 ToNumber(param1) + ToNumber(param2)。
console.log("abc" + 2) // abc2
console.log(1 + []) // “1”
console.log(null + 1) // 1
console.log(null + []) // "null"
console.log({} + []) // "[object Object]"。
console.log(1 + true); // 2
console.log(new Date() + 1); // Fri Nov 20 2020 10:50:35 GMT+0800 (中国标准时间)1

console.log( -0 + -0) // -0
console.log( -0 + 0) // 0
console.log( 0 + 0) // 0

注意:

如果在控制台中直接输入 {} + [] ,你会发现输出结果与 console.log 中的不同。

image

这是因为 {} 被当成了一个独立的代码块,所以 {} + [] 相当于执行 +[] ,所以输出为 0。

二元运算符(-、 *、%、/ )

算法:对两个参数执行 ToNumber 操作,再执行运算操作

关系运算符 (> < >= <=)

算法:

  1. 首先执行 ToPrimitive 操作,会将两个参数转换为原始值
  2. 如果两个参数都为 String 类型,则比较 Unicode encoding 大小。
  3. 否则将两个参数都转为 Number 值再进行数值大小比较。
    console.log(['2'] > 1) // true

相等运算符(==)

当两个参数类型不同时:

  1. 如果一个参数为 Object 类型,则会先执行 ToPrimitive 操作
  2. 如果 Result(1) 后,两个参数的类型仍然不同,则执行 ToNumber 操作
    console.log([] == 0) // true

if 条件判断语句

if 语句中的条件,如果仅有一个参数时,会执行 ToBoolean 操作。

if (1) {
    console.log("test")
}

// test

? : 三元运算符

三元运算符中的条件,如果仅有一个参数时,会执行 ToBoolean 操作。同 if

var a = 1 ? 'a' : 'b' // a = 'a'

逻辑运算符

逻辑运算符中的条件,如果仅有一个参数时,会执行 ToBoolean 操作。同 if

var a = 1 || 0  // a = 1
var a = 1 && 0  // a = 0