WuShaolin

悟已往之不谏,知来者之可追!

0%

阮一峰JS入门的强制转换部分


神奇的传送门 书籍


1. 简介、基本语法基本没啥问题,和以前的认知相同

2. 强制转换 知识

主要指使用NumberStringBoolean三个构造函数,手动将各种类型的值,转换成数字、字符串或者布尔值。

2.1 Number()函数

例如

//数值还是数值
Number(42)//42
//字符串 能全转 才能全转
Number('42') //42
//空字符串转为0
Number(' ')//0
// 布尔值:true 转成1,false 转成0
Number(' true')//1
Number(' false')//0
// undefined:转成 NaN
Number(undefined) // NaN
// null:转成0
Number(null) // 0

Number()很严格,比parseInt()严格。

parseInt('42 cats') // 42
Number('42 cats') // NaN 只要有一个不能转的字符就是NaN

Number函数会自动过滤一个字符串前导和后缀的空格。

Number('\t\v\r12.34\n') // 12.34

分割线强力来袭 ~


  • 强调一下对象的转换规则
    简单的规则是 ***简单的规则是,Number方法的参数是对象时,将返回NaN,除非是包含单个数值的数组。
    举例:
Number({a: 1}) // NaN
Number([1, 2, 3]) // NaN
Number([5]) // 5

接下来了解一下Number()背后的原理。哇擦嘞,以前真是不注意这些东西,菜鸡一枚啊。

1、调用对象自身的valueOf方法。如果返回原始类型的值,则直接对该值使用Number函数,不再进行后续步
骤。
2、如果valueOf方法返回的还是对象,则改为调用对象自身的toString方法。如果toString方法返回原始类型的值,则对该值使用Number函数,不再进行后续步骤。
3、如果toString方法返回的是对象,就报错。

原理不好理解,上栗子

var obj = {x: 1};
Number(obj) // NaN

// 等同于
if (typeof obj.valueOf() === 'object') {
  Number(obj.toString());
} else {
  Number(obj.valueOf());
}

上面的代码意思是:Number函数接收到了obj,先调用obj.valueOf()方法,判断是不是object,结果返回对象自身,于是,继续调用obj.toString方法,这时返回字符串[object Object],对这个字符串使用Number函数,必然得到NaN

默认情况下,对象的valueOf()方法总是会返回对象自身,所以一般会调用对象的toString()方法,如果toString()方法,返回对象的类型字符串(比如[object Object]),那么Number(),结果就是NaN;

Number({}) // NaN

如果toString()方法返回不是原始类型的值,就报错(这句话的另一层意思也就是toString()方法被重写了啊)

依然上栗子
obj对象重写了两个方法,注意 toString()方法返回的又是一个对象
报的错 TypeError: Cannot convert object to primitive value

var obj = {
  valueOf: function () {
    return {};
  },
  toString: function () {
    return {};
  }
};

Number(obj)
// TypeError: Cannot convert object to primitive value

2.2 String()函数

使用String函数,可以将任意类型的值转化成字符串。转换规则如下。

    1. 原始数据类型转换

数值:转为相应的字符串。
字符串:转换后还是原来的值。
布尔值:true转为”true”,false转为”false”。
undefined:转为”undefined”。
null:转为”null”。

String(123) // "123"
String('abc') // "abc"
String(true) // "true"
String(undefined) // "undefined"
String(null) // "null"
    1. 对象的转换
      String方法的参数如果是对象,返回一个类型字符串;如果是数组,返回该数组的字符串形式。
String({a: 1}) // "[object Object]"
String([1, 2, 3]) // "1,2,3"

背后的原理基本与Number()相同,只是方法的调用相反

1、先调用对象自身的toString方法。如果返回原始类型的值,则对该值使用String函数,不再进行以下步骤。
2、 如果toString方法返回的是对象,再调用原对象的valueOf方法。如果valueOf方法返回原始类型的值,则对该值使用String函数,不再进行以下步骤。
3、如果valueOf方法返回的是对象,就报错。

String({a: 1})
// "[object Object]"

// 等同于

String({a: 1}.toString())
// "[object Object]"

上面代码先调用对象的toString方法,发现返回的是字符串[object Object],就不再调用valueOf方法了。

如果toString法和valueOf方法,返回的都是对象,就会报错。

var obj = {
  valueOf: function () {
    console.log('valueOf');
    return {};
  },
  toString: function () {
    console.log('toString');
    return {};
  }
};

String(obj)
// TypeError: Cannot convert object to primitive value

2.3 Boolean()

除了以下六个值的转换结果为false,其他的值全部为true。

undefined
null
-0
0或+0
NaN
‘ ‘(空字符串)

Boolean(undefined) // false
Boolean(null) // false
Boolean(0) // false
Boolean(NaN) // false
Boolean('') // false
  • 注意一下
    注意,所有对象(包括空对象)的转换结果都是true,甚至连false对应的布尔对象new Boolean(false)也是true。
Boolean({}) // true
Boolean([]) // true
Boolean(new Boolean(false)) // true