javascript中的数据类型转换

1、转换过程中注意toString、toNumber、toBoolean、toPrimitive

可以简单理解前面三种为显式转换,而primitive为隐式强制类型转换,

a、toString:默认使用的是Object.prototype.toString(),除非该对象上定义了toString方法,类似的一种情况JOSN,也基本上算是一种显式强制类型转换,转换的时的规则基本和toString相同,只有个别不能处理的数据类型不一样,详细参考JOSN.stringify

b、toNumber:

需要特别注意

0 === -0 // true 、Object.is(0, -0)  // false    相对 === is方法现在能处理NaN了但又整出个0不等于-0………

String(0)和String(-0)都会转换成'0',应用到对象key上   a[0]和a[-0]使用的key都是a[0],解决办法是a[‘-0’]

Number(undefined) = > NaN

Number(null) = > 0

另外Number和windown.parseInt的行为是不一样的,虽然说多数情况他们返回值是一样的

parseInt

如果 parseInt 遇到了不属于radix参数所指定的基数中的字符那么该字符和其后的字符都将被忽略。接着返回已经解析的整数部分。parseInt 将截取整数部分。开头和结尾的空白符允许存在,会被忽略。

如果第一个字符不能被转换成数字,parseInt返回NaN。

https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/parseInt

用代码翻译下就是:

parseInt(' 1.x2v3', 10) // 1

parseInt('        1.x2v3     ', 10) // 1

parseInt('a        1.x2v3', 10) // NaN

以上表示parseInt,可以正常过滤掉前后的空格,如果trim后第一个字符不能转换成数值就会返回NaN,

《你不知道的JavaScript(中卷)》

ES5 之前的parseInt(..) 有一个坑导致了很多bug。即如果没有第二个参数来指定转换的基数(又称为radix),parseInt(..) 会根据字符串的第一个字符来自行决定基数。

从ES5 开始parseInt(..) 默认转换为十进制数,除非另外指定。如果你的代码需要在ES5之前的环境运行,请记得将第二个参数设置为10。

但用chrome(版本 65.0.3325.181(正式版本) (32 位))试了下parseInt如果不显式指定第二个参数,还是会自动根据传入值来设置转换基数(第二个参数),而不是默认为10,如:parseInt('0xAF') =》 175;parseInt('0xAF', 10) => 0

Number

Number(' 1.x2v3')  // NaN

Number('       1.x2v3     ')  // NaN

Number('11')  // 11

可以看出Number处理时,并没有对原字符串做任何处理,直接对原字符串转换成数字

parseInt => 解析字符串为数字

Number => 把字符串转换成数字

常见的转换操作

+        一元操作符

日期转为时间毫秒 +new Date()

a * 1

c、toBoolean:

a = new Boolean(false)

if(a){console.log(1)} // 1

这里的理解new 产生一个对象,上面的false可以换成其他的假值,而大部分对象都是真值,除了null、document.all

假值=》undefined、null、0、-0、NaN、false、''共7个假值,EMCA规范中并没有定义有哪些真假,所以可以认为除了假值以外的值都是真假

需要注意字符串中除了空字符串''是假值,其他字符串都为真值'0'

d、toPrimitive

首先调用对象的valueOf函数,如果返回值类型为原始值,则返回该值,否则再调用toString方法,下面的a+1换成a+'1'都遵循该规则,并不是大众说的期望数字才优先使用valueOf转换

a = {b:2};a+1 // "[object Object]1"

a.valueOf = function(){return 1}; a+1 // 2

a.valueOf = function(){return {}};  a+1 // "[object Object]1"

a.toString = function(){return 1}; a+1 // 2

=======

由于Object.create(null)创建的对象没有继承Object任何属性,所以

a = Object.create(null)

a + 1, a+'',都会报“Cannot convert object to primitive value”

最坑的+运算符

== 字符串和数字

var a = '1';var b = 1; a==b // true

把字符串转换成数字后再比较

== boolean

x == y

其中存在一个布尔值的情况,先把布尔值toNumber,这种情况比较简单true=>1, false=>0

var a = 3; b = {};

a == true // false    true=>1   3==1

b == true // false

// ============

== null和undefined的表现是一致的,即两者可以互换

(1) 如果x 为null,y 为undefined,则结果为true。

(2) 如果x 为undefined,y 为null,则结果为true。

var a = null;

var b;

a == b; // true

b == null; // true

a == false; // false

b == false; // false

a == ""; // false

b == ""; // false

a == 0; // false

b == 0; // false

以上加粗不要理解为先把false=>0, null=>0, true;如果==其中一个值为null,undefined那另外一个值也只有为null,undefined结果才为true

== 对象和非对象 x == y

(1) 如果Type(x) 是字符串或数字,Type(y) 是对象,则返回x == ToPrimitive(y) 的结果;

(2) 如果Type(x) 是对象,Type(y) 是字符串或数字,则返回ToPromitive(x) == y 的结果。

"0" == false; // true — 晕!

false == 0; // true — 晕!

false == ""; // true — 晕!

false == []; // true — 晕!

"" == 0; // true — 晕!

"" == []; // true — 晕!

0 == []; // true — 晕!

"" == 0; // true — 晕!

"" == [];

封装和解封

a = 'abc'

b = new String('abc')

a == b // true  这里可以完成b = > 'abc'的解封

而Object(undefined) == undefined/null或者Object(null) == null/undefined,不能完成=>null或者undefined的解封,Object(NaN)可以解封为NaN但是 NaN!=NaN

比较有意思的问题

if(a==10 && a == 100){ console.log(1)}

如果要满足上面的条件输出1,想下a的值

i = 10

a = { valueOf:function(){var c = i; i = i+90; return c}};

===================

a = []; a == !a // true   ([] == ![] // true)

![] 先把[]转换为布尔值为true,再反转!为false,最后表达式变成[] == false => [] == 0 

================

2 == [2]; // true   这个好理解 [2] => '2'

"" == [null]; // true  这个刚开始也是按上面的理解 [null] => 'null' ,这样理解的原因是String(null) // 'null',但这里显然是错的,

先理解array.join方法,在调用数组join方法时,如果元素的值为null和undefined,那该元素转转换成空字符串'',[null, 2, undefined].join() // ',2,'

If an element is undefined or null, it is converted to the empty string.

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/join

a = [null, 2 , undefined]

console.log(a + 1) // ,2,1

这点和stringify不太一样, JSON.stringify( [null, 2 , undefined]) // “[null,2,null]"

a + 1的结果

如果定义a.join方法,或者定义toString方法也有同样的效果

a = [null, 2 , undefined]

// a.toString = function(){ return 100}

a.join = function(){ return 200}

console.log(a + 1) // 201

如果同时定义join和toString

a = [null, 2 , undefined]

a.toString = function(){ return 100}

a.join = function(){ return 200}

console.log(a + 1) // 101

toString返回非基础数据类型

a = [null, 2 , undefined]

a.toString = function(){ return {}}

a.join = function(){ return 200}

console.log(a + 1) // 201

Cannot convert object to primitive value

个人猜测:数组toString方法会调用数组实例的join方法

==============

a > b // false

a < b // false

a >= b // true

a <= b // true

a == b // fable

满足以上条件确定a\b的值,理解以下两点

  • <>“抽象关系比较”先调用toPrimitive转换如果值出现非字符串,再转换为数字
  • >= 其实是执行<,然后再把结果取反!

==============

"0" == null; // false

"0" == undefined; // false

"0" == false; // true — 晕!

"0" == NaN; // false

"0" == 0; // true

"0" == ""; // false

false == null; // false

false == undefined; // false

false == NaN; // false

false == 0; // true — 晕!

false == ""; // true — 晕!

false == []; // true — 晕!

false == {}; // false

"" == null; // false

"" == undefined; // false

"" == NaN; // false

"" == 0; // true — 晕!

"" == []; // true — 晕!

"" == {}; // false

0 == null; // false

0 == undefined; // false

0 == NaN; // false

0 == []; // true — 晕!

0 == {}; // false

发表评论

电子邮件地址不会被公开。 必填项已用*标注