数值转换
- 有3个函数可以把非数值转换为数值:
Number()
;parseInt()
;parseFloat()
;
Number()
函数,即转型函数,可以用于任何数据类型,而另外两个函数则专门用于把字符串转换成数值。Number()
函数的转型规则如下:
- 如果是
Boolean
值,true
和false
将分别被转换为1
和0
; - 如果是数字值,只是简单的传入和返回;
- 如果是
null
值,返回0
; - 如果是
undefined
, 返回NaN
; - 如果是字符串,遵循下列规则:
- 如果是字符串中包含数字(包括前面带正号或者负号的情况),则将其转换为十进制数值,即”1”会变成
1
,"123"
会变成123
, 而"011"
会变成11
(注意: 前导的零被忽略了); - 如果字符串中包含有效的浮点格式,如
"1.1"
, 则将其转换为对应的浮点数值(同样,也会忽略前导零); - 如果字符串中包含有效的十六进制格式,例如
"0xf"
, 则将其转换为相同大小的十进制整数值; - 如果字符串是空的(不包含任何字符),则将其转换为
0
; - 如果字符串中包含除上述格式之外的字符,则将其转换为
NaN
;
- 如果是字符串中包含数字(包括前面带正号或者负号的情况),则将其转换为十进制数值,即”1”会变成
- 如果是对象,则调用对象的
valueOf()
方法,然后依照前面的规则将转换返回的值。如果转换的结果是NaN
, 则调用对象的toString()
方法,然后再次依照前面的规则转换返回的字符串值。
- 如果是
- 根据这么多的规则使用
Number()
把各种数据类型转换为数值确实有点复杂。下面还是给出几个具体的例子:
var num1 = Number("Hello world!"); // NaN
var num2 = Number(" "); // 0
var num3 = Number("00000000012"); // 12
var num4 = Number(true); // 1
- 后话:一元操作符的操作与
Number()
函数相同。 - 由于
Number()
函数在转换字符串时比较复杂而且不够合理,因此在处理整数的时候更常用的是parseInt()
函数。 parseInt()
函数在转换字符串时,更多的是看其是否符合数值模式。它会忽略字符串前面的空格,直至找到第一个非空格字符。- 如果第一个字符不是数字字符或者负号,
parseInt()
就会返回NaN
;也就是说,用parseInt()
转换空字符串会返回NaN
(Number()
函数对空字符串返回0)。 - 如果第一个字符串是数字,
parseInt()
会继续解析第二个字符,直到解析完所有后续字符或者遇到了一个非数字字符。例如,"1234blue"
会被转换为1234
,因为"blue"
会被完全忽略。类似地,"22.5"
会被转换为22
, 因为小数点并不是有效的数字字符。 - 如果字符串中的第一个字符是数字字符,
parseInt()
也能够识别出各种整数格式(即十进制、八进制和十六进制数)。也就是说,如果字符串以"0x"
开头且后跟数字字符,就会将其当作一个十六进制整数;如果字符串以"0"
开头且后跟数字字符,则会将其当作一个八进制整数来解析。 - 为了更好地理解
parseInt()
函数的转换规则,下面给出了例子:
var num1 = parseInt("1234blue"); // 1234
var num2 = parseInt(" "); // NaN
var num3 = parseInt("0xA"); // 10(十六进制整数)
var num4 = parseInt(22.5); // 22
var num5 = parseInt("070"); // 56(八进制整数)
var num6 = parseInt("70"); // 70(十进制整数)
var num7 = parseInt("0xf"); // 15(十六进制整数)
- 在使用
parseInt()
解析想八进制字面量的字符串时,ECMAScript 3和5存在分歧。例如:
// ECMAScript 3认为是56(八进制整数),ECMAScript 5认为是0(十进制整数)
var num = parseInt("070");
- 在ECMAScript 5中, 即使是在严格模式下也会如此。
- 为了消除在使用
parseInt()
函数时可能导致的上述困惑,可以为这个函数提供第二个参数;转换时使用的基数(即多少进制)。如果知道要解析的值是是十六进制格式的字符串,那么指定基数16
作为第二个参数,可以保证得到正确的结果,例如:
var num = parseInt("0xAF", 16); // 175
- 实际上,如果指定了
16
作为第二个参数,字符串可以不带前面的"0x"
, 如下所示:
var num1 = parseInt("AF", 16); // 175
var num2 = parseInt("AF"); // NaN
- 第一个转换传入了基数,明确告诉
parseInt()
要解析一个十六进制格式的字符串; 而第二个转换发现第一个字符不是数字字符, 因此就自动终止。 - 指定基数会影响到转换的输出结果。例如:
var num1 = parseInt("10", 2); //2 (按二进制解析)
var num2 = parseInt("10", 8); //8 (按八进制解析)
var num3 = parseInt("10", 10); //10 (按十进制解析)
var num4 = parseInt("10", 16); //16 (按十六进制解析)
- 不指定基数意味着
parseInt()
决定如何解析输入的字符串,因此为了避免错误的解析,我们建议无论在什么情况下都明确指定基数。 - 题外话:
- 在多数情况下,要解析的都是十进制数值,因此始终将10作为第二个参数是非常必要的。
- 与
parseInt()
的函数类似,parseFloat()
也是从第一个字符(位置0)开始解析每个字符。而且也是一直解析到字符串末尾,或者解析到遇见第一个无效的浮点数为止。也就是说,字符串中的第一个小数点是有效的,而第二个小数点是无效的了。因此它后面的字符串将被忽略。举例来说: “22.34.5”将会被转换为”22.34”。 - 除了第一个小数点有效外,
parseInt()
和parseFloat
的第二个区别在于它始终都会忽略前导的零。 parseFloat()
可以识别前面讨论过的所有浮点数数值格式,也包括十进制整数格式。但十六进制格式的字符串则始终会被转换成0。- 由于
parseFloat()
只解析十进制值,因此它没有用第二个参数指定基数的用法。 - 最后还是要注意一点: 如果字符串包含的是一个可解析为整数的值(没有小数点,或者小数点后都是零),
parseFloat()
会返回整数。
var num1 = parseFloat("123blue"); // 1234(整数)
var num2 = parseFloat("0xA"); // 0
var num3 = parseFloat("22.5"); // 22.5
var num4 = parseFloat("22.34.5"); // 22.34
var num5 = parseFloat("0908.5"); // 908.5
var num6 = parseFloat("3.125e7"); // 31250000
String
类型:
String
类型用于表示零或者多个16位Unicode
字符组成的字符序列,即字符串。字符串可以用双引号(“)或者单引号(‘)表示,因此下面两种字符的写法都是有效的:
var firstName = "Nicholas";
var lastName = "Zakas";
- 与PHP中的双引号和单引号会影响对字符串的解释方式不同,ECMAScript中的这两种语法形式没有什么区别。用双引号表示的字符串和用单引号表示的字符串完全相同。不过, 以双引号开头的字符串也必须是以双引号结尾,而以单引号开头的字符串必须是以单引号结尾。
var firstName = 'Nicholas"; // 语法错误(左右引号必须匹配)
- 字符字面量
String
数据类型包好一些特殊的字符字面量,也叫转义序列,用于表示非打印字符,或者具有其他用途的字符。这些字符字面量如下表示:
字面量 | 含义 |
---|---|
\n | 换行 |
\t | 制表 |
\b | 空格 |
\r | 回车 |
\f | 换页符 |
\ | 斜杠 |
\’ | 单引号(‘),早使用单引号表示的字符串中使用。例如: ‘He said, \’hey.\” |
\” | 双引号(“),早使用双引号表示的字符串中使用。例如: “He said, \”hey.\”“ |
\xnn | 以十六进制代码nn表示的一个字符(其中n为0~F)。例如, \x41表示”A” |
\unnnn | 以十六进制代码nnnn表示的一个Unicode字符(其中n为0~F)。例如, \u03a3表示希腊字符 |
- 这些字符字面量可以出现在字符串中的任意位置,而且也将被作为一个字符串来解析,如下面的例子所示:
var text = "This is the letter sigma: \u03a3.";
- 这个例子中的变量
test
有28个字符,其中6个字符长的转义序列表示一个字符。 - 任何字符串的长度都可以通过访问其
length
属性取得,例如:
alert(text.length); //输出28
- 这个属性返回的字符数包括
16
个字符的数目。如果字符串中包含双字节字符,那么length
属性可能不会精确地返回字符串中的字符数目。 - 字符串的特点:
ECMAScript
中的字符串是不可变的,也就是说,字符串一旦创建,它们的值就不能改变。要改变某个变量保存的字符串,首先要销毁原来的字符串,然后再另一个包含新值的字符串填充该变量。例如:
var lang = "Java"
lang = lang + "Script"
- 以上示例中的变量
lang
开始时包含字符串”Java”。而第而行代码把lang
的值重新定义为”Java”与”Script”的组合,即”JavaScript”。实现这个操作的过程如下: 首先创建一个能容纳10个字符的新字符串,然后在这个字符串中填充”Java”和”Script”,最后一步是销毁原来的字符串”Java”和字符串”Script”,因为这两个字符串已经没用了。这个过程是在后台发生的,而这也是在某些旧版本的浏览器(例如版本低于1.0的Firefox, IE6等)中拼接字符串时速度很慢的原因所在。但这些浏览器后来的版本已经解决了这个版本低效率问题。 - 转换为字符串:
- 要把一个值转换为一个字符串有两种方式。第一种是使用几乎每个值都有的
toString()
方法。这个方法唯一要做的就是返回相应值的字符串表现。来看下面的例子:
var age = 11;
var ageAsString = age.toString(); // 字符串"11"
var found = true;
var foundAsString = found.toSring(); // 字符串"true"
- 数值、布尔值、对象和字符串值(没错,每个字符串也都有一个
toString()
方法,该方法返回字符串的一个副本)都有toString()
方法。但null
和undefined
值都没有这个方法。 - 多数情况下,调用
toString()
方法不必传递参数。但是在调用数值的toString
方法时,可以传递一个参数: 输出数值的基数。默认情况下,toString()
方法以十进制格式返回数值的字符串表示。而通过传递基数,toString()
可以输出以二进制、八进制、十六进制,乃至其他任意有效进制格式表示的字符串值,下面给出几个例子:
var num = 10;
console.log(num.toString()); // "10"
console.log(num.toString(2)); // "1010"
console.log(num.toString(8)); // "12"
console.log(num.toString(10)); // "10"
console.log(num.toString(16)); // "a"
- 通过指定基数,
toString()
方法会改变输出的值。而数值10
根据基数的不同, 可以在输出时被转换为不同的数值格式。默认的(没有参数的)输出值与指定基数10
时的输出值相同。 - 在不知道要转换的值是不是
null
或者undefined
的情况下,还可以使用转型函数String()
,这个函数能够将任何类型的值转换为字符串。String()
函数遵循下列转换规则:
- 如果有值
toString()
方法,则调用该方法(没有参数)并返回相应的结果; - 如果是值
null
, 则返回"null"
; - 如果值是
undefined
,则返回"undefined"
。
- 如果有值
- 例子:
var value1 = 10;
var value2 = true;
var value3 = null;
var value4;
console.log(String(value1)); // "10"
console.log(String(value2)); // "true"
console.log(String(value3)); // "null"
console.log(String(value4)); // "undefined"
- 数值、布尔值、
null
和undefined
。数值和布尔值的转换结果与调用toString()
方法得到的结果相同。因为null
和undefined
没有toString()
方法,所以String()函数就返回了这两个值的字面量。
JackDan Thinking