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

数据类型之间的转换(显示转换&&隐式转换) #20

Open
xuexueq opened this issue Oct 9, 2018 · 0 comments
Open

数据类型之间的转换(显示转换&&隐式转换) #20

xuexueq opened this issue Oct 9, 2018 · 0 comments
Labels
Javascript Javascript

Comments

@xuexueq
Copy link
Owner

xuexueq commented Oct 9, 2018

数据类型的转换

强制转换

强制转换主要是指使用Number()、String()和Boolean()三个构造函数,手动将各种类型的值,转换成number、string和boolean。

    1. Number()可以将任意类型的值转化成数值。
// 数值:转换后还是原来的值 
Number(123); // => 123 

// 字符串:如果可以被解析为数值,则转换为相应的数值 
Number('123'); // => 123 

// 字符串:如果不可以被解析为数值,返回NaN 
Number('123abc'); // => NaN 

// 空字符串转换为0 
Number(''); // => 0 // 

布尔值:true转成1,false转成0 
Number(true); // => 1 
Number(false); // => 0 

// undefined: 转换成NaN 
Number(undefined); // => NaN 

// null: 转成0 
Number(null); // => 0 

// 对象:将返回NaN,除非是包含单个数值的数组 
Number({a: 1}); // => NaN 
Number([1, 2, 3]); // => NaN 
Number([1]); // => 1

除了 Number() 之外,还可以通过 parseInt() 和 parseFloat() 来转换

【不同】parseInt() 与 parseFloat() 只能在 String 类型上调用,而 Number() 不仅限于 String 类型,比如 Date 类型上也可以使用。

parseInt(string, radix)】: 首先查看位置 0 处的字符,判断它是否是个有效数字;如果不是,该方法将返回NaN,不再继续执行其他操作。但如果该字符是有效数字,该方法将查看位置 1 处的字符,进行同样的测试。这一过程将持续到发现非有效数字的字符为止,此时parseInt()将把该字符之前的字符串转换成数字。

var iNum1 = parseInt("12345red");// => 12345 
var iNum1 = parseInt("0xA"); // => 10 
var iNum1 = parseInt("56.9"); // => 56 
var iNum1 = parseInt("red"); // => NaN

parseInt()方法还有基模式,可以把二进制、八进制、十六进制或其他任何进制的字符串转换成整数。基是由parseInt()方法的第二个参数指定的。

[1,2,3,4].map(parseInt)结果是?

[1, NaN, NaN, NaN]

相当于

parseInt(1,0) //1
parseInt(2,1) //NaN 1为基数转换为NaN(进制规则)
parseInt(3,2) //NaN
parseInt(4,3) //NaN

参数radix: 转换所采用的基数,2到36之间。
解析规则: string参数被看做radix指定进制下的数要把它转换成十进制的整数。

没有指定基数/基数为0时

  • 参数string以“0x”或“0X”开头,radix取16;
  • 参数string以“0”开头,ECMAScript5规定radix只能取10,然而ECMAScript3允许- radix取8。具体的解析结果依然由实现环境而定。
  • 其他情况下,radix取10.

基数为1或大于36时:解析结果为NaN

基数处于2到36之间时

  • 如果string参数的第一个字符(除空白以外),不属于radix指定进制下的字符,解析结果为NaN;
  • 如果第一个字符属于radix指定进制下的字符,则解析到不属于radix指定进制下的字符时,将忽略该字符及其后的所有字符。
parseInt(2,4) //2
parseInt(2,3) //2
parseInt(2,2) //NaN
parseInt(5,3) //NaN

parseFloat(string)】:parseFloat()方法与parseInt()方法的处理方式相似,从位置 0 开始查看每个字符,直到找到第一个非有效的字符为止,然后把该字符之前的字符串转换成整数。

不过,对于这个方法来说,第一个出现的小数点是有效字符。如果有两个小数点,第二个小数点将被看作无效的。

该方法没有基数模式。

字符串必须以十进制形式表示浮点数,而不是用八进制或十六进制。该方法会忽略前导 0,所以八进制数 0102 将被解析为 102。对于十六进制数 0xA,该方法将返回 NaN,因为在浮点数中,x 不是有效字符。(注释:经测试,具体的浏览器实现会返回 0,而不是 NaN。)

var fNum1 = parseFloat("12345red");// => 12345 
var fNum2 = parseFloat("0xA"); // => NaN 
var fNum3 = parseFloat("11.2"); // => 11.2 
var fNum4 = parseFloat("11.22.33");// => 11.22 
var fNum5 = parseFloat("0102"); // => 102 
var fNum1 = parseFloat("red"); // => NaN

Number()】:Number()函数的强制类型转换与parseInt()和parseFloat()方法的处理方式相似,只是它转换的是整个值,而不是部分值

Number()属于强类型转换,使用强制类型转换可以访问特定的值,即使它是另一种类型。

parseInt()和parseFloat()方法只转换第一个无效字符之前的字符串,因此 “1.2.3” 将分别被转换为 “1” 和 “1.2”。

用Number()进行强制类型转换,”1.2.3″ 将返回 NaN,因为整个字符串值不能转换成数字。如果字符串值能被完整地转换,Number()将判断是调用parseInt()方法还是parseFloat()方法。

var date = new Date('Tue Jun 14 2016 00:00:00'); 
console.log(Number(date));// => 1465833600000

Number(false); // => 0 
Number(true); // => 1 
Number(undefined); // => NaN 
Number(null); // => 0 
Number('1.2'); // => 1.2 
Number('12'); // => 12 
Number('1.2.3'); // => NaN 
Number(new Object({}));// => NaN 
Number(50);  // 50
    1. 使用String(),可以将任意类型的值转化成字符串。
// 数值: 转为相应的字符串 
String(123); // => '123' 

// 字符串: 转换后还是原来的值 
String('123'); // => '123' 

// 布尔值: true转为'true',false转为'false'
String(true); // => 'true' 
String(false); // => 'false' 

// undefined: 转为'undefined' 
String(undefined); // => 'undefined' 

// null: 转为'null' 
String(null); // => 'null' 

// 对象:返回一个类型字符串 
// 数组:返回该数组的字符串形式 
String({a: 1}); // => [object Object] 
String([1, 2, 3]); // => '1,2,3'

toString()String()】的主要区别就在于String()还能转换null和undefined值。

String(null); // 'null'
String(undefined); // 'undefined'
null.toString(); // 报错

// 但可以借用toString()
Object.prototype.toString.call(null); // "[object Null]"
Object.prototype.toString.call(undefined); // "[object Undefined]"

new String()】转换出来的是一个object。而这个对象是一个对基本类型值str的包装器对象。

    1. 使用Boolean(),可以将任意类型的变量转为布尔值。

它的转换规则相对简单:除了以下六个值的转换结果为false,其他的值全部为true。

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

所有对象的布尔值都是true,这是因为JavaScript语言设计的时候,出于性能的考虑,如果对象需要计算才能得到布尔值,对于obj1 && obj2这样的场景,可能会需要较多的计算。为了保证性能,就统一规定,对象的布尔值为true。

隐式类型转换

隐式转换是以强制转换为基础的。

多数情况下,在JavaScript中比如遇到 -、*、/ 和 % 等算术运算都会把操作数转换成数字的,但是 + 和其他的有点不一样,有些情况下,它是算术加号,有些情况下是字符串连接符,具体的看它的操作数。

// 不同类型的数据互相运算 
123 + 'abc'; // => '123abc' 

// 对非布尔值类型的数据求布尔值 
if ('abc') { 
	console.log('hello'); // => 'hello' 
} 

// 对非数值类型的数据使用一元素运算符即+和- 
+ {foo: 'bar'}; // => NaN 
- [1,2,3]; // => NaN

1. 字符串的隐式转换规则

123 + 'abc' // '123abc'
'abc' + 123 // 'abc123's
3 + '12' // '321'
'12' + 3 // '123'
true + '5' // 'true5'
'5' + true // '5true'
false + '5' // 'false5'
'5' + false // '5false'
'5' + function (){} // "5function (){}"
(function (){}) + '2' // 'function(){}2'
'5' + undefined // "5undefined"
undefined + '5' // 'undefined5'
'5' + null // "5null"
null + '5' // 'null5'
'5' + {} // "5[object Object]"
{} + '5' // 5 注意转换成数字了
'5' + [] // "5"
[] + '5' // '5'
  • 字符串的自动转换,主要发生在加法运算时。会将非字符串的数据自动转为字符串。系统内部会自动调用 String() 函数。

2. 数字的隐式转换规则

'5' - '2' // 3 
'5' * '2' // 10 
true - 1 // 0 
false - 1 // -1 
'1' - 1 // 0 
'5' * [] // 0 
false / '5' // 0 
'abc' - 1 // NaN
{} - 1 // -1 注意和空对象进行算术运算(空对象在前) 无论是加法还是其他 会自动转换为数值
1 - {} // NaN
  • 除了加法运算符有可能把运算子转为字符串,其他运算符都会把运算子自动转成数值。系统内部会自动调用Number()函数。
+'abc' // NaN 
-'abc' // NaN 
+true // 1
-false // 0
  • 一元运算符也会把运算子转成数值。
3 + true; // 4
1 + 2 + '3'; // '33'

此外,需要注意的是,+的运算符方向是从左到右。


在JavaScript中,隐式类型思考换有时候会隐藏一些错误的,比如null会转换为0,undefined会转换成NaN。需要注意的是:NaN和NaN是不相等的

NaN === NaN // false

虽然在JavaScript中提供了isNaN来检测某个值是否为NaN,但是,这也不太精确的,在调用isNaN之前,本知就存在一个隐式转换的过程,它会把那些原本不是NaN的值转换为NaN。

isNaN('foo'); // => true 
isNaN(undefined); // => true 
isNaN({}); // => true 
isNaN({a:'xxx'}); // => true

3. 对象的隐式转换规则

// 对象可以转换成原始值的,把它转换成字符串 
'The Math Objec: ' + Math; // => 'The Math Object:' [object Math]' 
'The JSON Object:' + JSON; // => 'The JSON Object:' [object JSON]' 

// 对象转换成字符串 
Math.toString(); // => '[object Math]' 
JSON.toString(); // => '[object JSON]' 

// 对象可以转换成数字 
'J' + {toString: function (){ return 'S'}}; // => 'JS' 
2 * {valueOf: function() {return 3}}; // => 6

如果,一个对象同时存在 valueOf() 和 toString() 时,那么valueOf()总是会先被调用。

var obj = { 
	toString: function() { 
		return '[object MyObject]'; 
	}, 
	valueOf: function() { 
		return 1 
	} 
}; 
'Object: ' + obj; // => 'Object: 1'

但是,多数情况下,这都不是我们想要的,一般的,尽可能使 valueOf() 和 toString() 表示的值相同。

valueOf()toStringOf()

4. 布尔值的隐式转换规则

当JavaScript遇到预期为布尔值的地方(比如if语句的条件部分),就会将非布尔值的参数自动转换为布尔值。系统内部会自动调用 Boolean()函数。

因此除了以下六个值,其他都是自动转为true。

  • undefined
  • null
  • -0
  • 0 或 +0
  • ' '
if ( !undefined 
	&& !null 
	&& !0 
	&& !NaN 
	&& !'' 
) { 
	console.log('true'); 
} // true

// 写法一 
expression ? true : false 

// 写法二 
!! expression

References

JavaScript中数据类型转换

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

No branches or pull requests

1 participant