Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

JS 类型转换的规则是什么? #16

Open
YvetteLau opened this issue Apr 21, 2019 · 2 comments
Open

JS 类型转换的规则是什么? #16

YvetteLau opened this issue Apr 21, 2019 · 2 comments

Comments

@YvetteLau
Copy link
Owner

No description provided.

@YvetteLau
Copy link
Owner Author

类型转换的规则三言两语说不清,真想哇得一声哭出来~

JS中类型转换分为 强制类型转换 和 隐式类型转换 。

  • 通过 Number()、parseInt()、parseFloat()、toString()、String()、Boolean(),进行强制类型转换。

  • 逻辑运算符(&&、 ||、 !)、运算符(+、-、*、/)、关系操作符(>、 <、 <= 、>=)、相等运算符(==)或者 if/while 的条件,可能会进行隐式类型转换。

强制类型转换

1.Number() 将任意类型的参数转换为数值类型

规则如下:

  • 如果是布尔值,true和false分别被转换为1和0
  • 如果是数字,返回自身
  • 如果是 null,返回 0
  • 如果是 undefined,返回 NAN
  • 如果是字符串,遵循以下规则:
    1. 如果字符串中只包含数字(或者是 0X / 0x 开头的十六进制数字字符串,允许包含正负号),则将其转换为十进制
    2. 如果字符串中包含有效的浮点格式,将其转换为浮点数值
    3. 如果是空字符串,将其转换为0
    4. 如不是以上格式的字符串,均返回 NaN
  • 如果是Symbol,抛出错误
  • 如果是对象,则调用对象的 valueOf() 方法,然后依据前面的规则转换返回的值。如果转换的结果是 NaN ,则调用对象的 toString() 方法,再次依照前面的规则转换返回的字符串值。

部分内置对象调用默认的 valueOf 的行为:

对象 返回值
Array 数组本身(对象类型)
Boolean 布尔值(原始类型)
Date 从 UTC 1970 年 1 月 1 日午夜开始计算,到所封装的日期所经过的毫秒数
Function 函数本身(对象类型)
Number 数字值(原始类型)
Object 对象本身(对象类型)
String 字符串值(原始类型)
Number('0111'); //111
Number('0X11') //17
Number(null); //0
Number(''); //0
Number('1a'); //NaN
Number(-0X11);//-17

2.parseInt(param, radix)

如果第一个参数传入的是字符串类型:

  1. 忽略字符串前面的空格,直至找到第一个非空字符,如果是空字符串,返回NaN
  2. 如果第一个字符不是数字符号或者正负号,返回NaN
  3. 如果第一个字符是数字/正负号,则继续解析直至字符串解析完毕或者遇到一个非数字符号为止

如果第一个参数传入的Number类型:

  1. 数字如果是0开头,则将其当作八进制来解析(如果是一个八进制数);如果以0x开头,则将其当作十六进制来解析

如果第一个参数是 null 或者是 undefined,或者是一个对象类型:

  1. 返回 NaN

如果第一个参数是数组:
1. 去数组的第一个元素,按照上面的规则进行解析

如果第一个参数是Symbol类型:
1. 抛出错误

如果指定radix参数,以radix为基数进行解析

parseInt('0111'); //111
parseInt(0111); //八进制数 73
parseInt('');//NaN
parseInt('0X11'); //17
parseInt('1a') //1
parseInt('a1'); //NaN
parseInt(['10aa','aaa']);//10

parseInt([]);//NaN; parseInt(undefined);

parseFloat

规则和parseInt基本相同,接受一个Number类型或字符串,如果是字符串中,那么只有第一个小数点是有效的。

toString()

规则如下:

  • 如果是Number类型,输出数字字符串
  • 如果是 null 或者是 undefined,抛错
  • 如果是数组,那么将数组展开输出。空数组,返回''
  • 如果是对象,返回 [object Object]
  • 如果是Date, 返回日期的文字表示法
  • 如果是函数,输出对应的字符串(如下demo)
  • 如果是Symbol,输出Symbol字符串
let arry = [];
let obj = {a:1};
let sym = Symbol(100);
let date = new Date();
let fn = function() {console.log('稳住,我们能赢!')}
let str = 'hello world';
console.log([].toString()); // ''
console.log([1, 2, 3, undefined, 5, 6].toString());//1,2,3,,5,6
console.log(arry.toString()); // 1,2,3
console.log(obj.toString()); // [object Object]
console.log(date.toString()); // Sun Apr 21 2019 16:11:39 GMT+0800 (CST)
console.log(fn.toString());// function () {console.log('稳住,我们能赢!')}
console.log(str.toString());// 'hello world'
console.log(sym.toString());// Symbol(100)
console.log(undefined.toString());// 抛错
console.log(null.toString());// 抛错

String()

String() 的转换规则与 toString() 基本一致,最大的一点不同在于 nullundefined,使用 String 进行转换,null 和 undefined对应的是字符串 'null''undefined'

Boolean

除了 undefined、 null、 false、 ''、 0(包括 +0,-0)、 NaN 转换出来是false,其它都是true.

隐式类型转换

&& 、|| 、 ! 、 if/while 的条件判断

需要将数据转换成 Boolean 类型,转换规则同 Boolean 强制类型转换

运算符: + - * /

+ 号操作符,不仅可以用作数字相加,还可以用作字符串拼接。

仅当 + 号两边都是数字时,进行的是加法运算。如果两边都是字符串,直接拼接,无需进行隐式类型转换。

除了上面的情况外,如果操作数是对象、数值或者布尔值,则调用toString()方法取得字符串值(toString转换规则)。对于 undefined 和 null,分别调用String()显式转换为字符串,然后再进行拼接。

console.log({}+10); //[object Object]10
console.log([1, 2, 3, undefined, 5, 6] + 10);//1,2,3,,5,610

-*/ 操作符针对的是运算,如果操作值之一不是数值,则被隐式调用Number()函数进行转换。如果其中有一个转换除了为NaN,结果为NaN.

关系操作符: ==、>、< 、<=、>=

> , <<=>=

  1. 如果两个操作值都是数值,则进行数值比较
  2. 如果两个操作值都是字符串,则比较字符串对应的字符编码值
  3. 如果有一方是Symbol类型,抛出错误
  4. 除了上述情况之外,都进行Number()进行类型转换,然后再进行比较。

注: NaN是非常特殊的值,它不和任何类型的值相等,包括它自己,同时它与任何类型的值比较大小时都返回false。

console.log(10 > {});//返回false.
/**
 *{}.valueOf ---> {}
 *{}.toString() ---> '[object Object]' ---> NaN
 *NaN 和 任何类型比大小,都返回 false
 */

相等操作符:==

  1. 如果类型相同,无需进行类型转换。
  2. 如果其中一个操作值是 null 或者是 undefined,那么另一个操作符必须为 null 或者 undefined 时,才返回 true,否则都返回 false.
  3. 如果其中一个是 Symbol 类型,那么返回 false.
  4. 两个操作值是否为 string 和 number,就会将字符串转换为 number
  5. 如果一个操作值是 boolean,那么转换成 number
  6. 如果一个操作值为 object 且另一方为 string、number 或者 symbol,是的话就会把 object 转为原始类型再进行判断(调用object的valueOf/toString方法进行转换)

对象如何转换成原始数据类型

如果部署了 [Symbol.toPrimitive] 接口,那么调用此接口,若返回的不是基础数据类型,跑出错误。

如果没有部署 [Symbol.toPrimitive] 接口,那么先返回 valueOf() 的值,若返回的不是基础类型的值,再返回 toString() 的值,若返回的不是基础类型的值, 则抛出异常。

//先调用 valueOf, 后调用 toString
let obj = {
    [Symbol.toPrimitive]() {
        return 200;
    },
    valueOf() {
        return 300;
    },
    toString() {
        return 'Hello';
    }
}
//如果 valueOf 返回的不是基本数据类型,则会调用 toString, 
//如果 toString 返回的也不是基本数据类型,会抛出错误
console.log(obj + 200); //400

@matteokjh
Copy link

你好,请问object和symbol什么时候会相等?不是说symbol是唯一标识吗?我还以为它不等于任何其它东西

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants