前言
前方高能预警:本文中Number类型
及其基础、硬核且无聊,导致大部分人觉得这些内容没什么用。如果你中途坚持不住,建议点赞,收藏后,改日再战。
对于初次接触JavaScript的朋友来说,本文信息量略为丰富,建议收藏,多多复习,练习。
如果你为了追求极致的学习速度,想知道JavaScript与C++/Java不同之处,请直接翻到文末小结部分。
数据类型
ECMAScript中有5种基本数据类型:Undefined
, Null
, Boolean
, Number
和String
和一种复杂数据类型Object
。
ECMAScript不支持任何创建自定义类型的机制,所有值最终都将是上述6种数据类型之一。
typeof操作符
对一个值使用typeof
操作符,可能会返回下列某个字符串:
-
"undefined"
,变量未被初始化,或变量未被定义。 -
"boolean"
,布尔值。 -
"string"
,字符串。 -
"number"
,数值。 -
"object"
,对象或null
。 -
"function"
,函数。
Undefined类型
Undefined类型
只有一个值,就是undefined
。
在使用var
声明变量但未对其进行初始化时,该值为undefined
。
包含undefined
值的变量和尚未定义的变量是不一样的,如下例:
var message; //该变量默认为undefined。
//下面变量未被声明
//var age;
alert(message); //undefined
alert(age); //ReferenceError: age is not defined.
迷惑的是,在使用typeof
操作符时,两者的值都是undefined
,如下例:
alert(typeof message); //"undefined"
alert(typeof age); //"undefined"
所以,强烈推荐显式的初始化变量。这样,我们就可以知道被检测的变量的状态是没声明,而不是尚未初始化。**
Null类型
Null类型也只有一个值,就是null
。
从逻辑角度来看,null
值表示一个对象的空指针,事实上,这也就解释了为什么在使用typeof
操作符检测null
时,会返回"object"。如下例所示。
var car = null;
alert(typeof car); //"object"
如果定义的变量要用于保存对象的话,最好将该变量初始化为null
。这样只需要检查null
值就可以知道相应的变量是否已经保存了一个变量引用。
var car = null;
if( car!=null ){
//对car对象执行某些操作
}
需要注意的是,undefined
的值是派生自null
值的,因此ECMA-262规定对它们进行相等性测试时,必须返回true。
alert( undefined==null ); //true
无论在什么情况下都没必要把一个变量的值显式设置为undefined,这样可以有助于区分undefined
与null
。
Boolean类型
Boolean
类型是ECMAScript中使用最多的一种类型,该类型只有两个字面值true
和false
。(注意:true
和false
是区分大小写的)
ECMAScript中所有类型的值都可以通过Boolean()
函数来转换为相应的等价值。
var message = "Hello World!";
alert(Boolean(message)); //true
下表为各类数据类型与Boolean
类型的转换规则。
数据类型 | 转换为ture | 转换为false |
---|---|---|
Boolean | true | false |
String | 任何非空字符串 | "" |
Number | 任何非零数字值(包括无穷大) | 0和NaN |
Object | 任何对象 | null |
Undefined | 无 | undefined |
Number类型
最基本的字面值格式是十进制整数,如下:
var intNum = 123;
除十进制外,整数还可以通过八进制或十六进制的字面值来表示。
八进制
八进制字面值的第一位必须是零(0),然后是八进制数字序列(0~7)。如果字面值中的数值超出了范围,那么前导0将会被忽略,后面的数值按照十进制解析。如下例:
var octalNum1 = 070; //八进制的56
var octalNum2 = 079; //无效的八进制数值,解析为79
var octalNum3 = 08; //无效的八进制数据,解析为8
八进制在严格模式下是无效的,会导致支持的JavaScript引擎抛出错误。
十六进制
十六进制的前两位必须是0x,后跟任何十六进制数字(0~9及A~F)。其中,A~F字母即可以大写,也可以小写。
var hexNum1 = 0xA; //十六进制的10
var hexNum2 = 0x1f; //十六进制的31
在进行算数运算时,所有以八进制和十六进制表示的数值最终都将转换为十进制数值。
浮点数值
浮点数值,该数值中必须包含一个小数点,并且小数点后面至少得有一位数字。
小数点前面可以省略整数,但不推荐。
var floatNum1 = 1.1;
var floatNum2 = 0.1;
var floatNum3 = .1; //有效,但不推荐。
由于保存浮点整数需要的内存空间是保存整数的两倍,所以ECMAScript会不失时机的将浮点数值转换为整数值。
var floatNum1 = 1.; //小数点后面没有数字,解析为1。
var floatNum2 = 10.0; //整数,解析为10。
对于极大或极小的值,可以使用e表示法(科学计数法)表示的浮点数表示。
var floatNum1 = 3.125e7; //3.125*10^7 = 31250000
var floatNum2 = 3e-17; //3*10^(-17) = 0.00000000000000003
浮点数值的最高精度是17位小数,但在算术计算时,其精度远远不如整数。
alert(0.1+0.2); //0.30000000000000004
alert(0.1+0.2==0.3); //false
数值范围
ECMAScript能够表示最小的数值保存在Number.MIN_VALUE
,大多数浏览器中,其值为5e-324
。
ECMAScript能够表示最大的数值保存在Number.MAX_VALUE
中,大多数浏览器中,其值为1.7976931348623157e+308
。
当某次计算的结果得到了超出JavaScript数值范围的值时,这个数值会自动转换为Infinity
值。
当该值为正无穷时,得到的是Infinity
值;该值为负无穷时,得到的是-Infinity
值。
当某次计算的值返回了正或负Infinity
值时,该值无法继续参与下一次计算,因为Infinity
不是能够参与计算的数值。
我们可以通过isFinite()
函数来判断一个数值是否是无穷。
alert(isFinite(0)); //false
alert(isFinite(Number.MAX_VALUE+1)); //true
NaN
NaN
,非数值,是一个特殊的数值,用于表示一个本来要返回数值的操作未返回数值的情况。例如:
alert(1/0); //NaN
NaN
本身有两个非比寻常的特点。
-
任何涉及与
NaN
操作,结果都是NaN
。(好比0乘任何数都得0) NaN
不与任何数值相等,包括NaN
自己。
alert(0*NaN); //NaN
alert(0/NaN); //NaN
alert(0+NaN); //NaN
alert(0-NaN); //NaN
alert(NaN==NaN); //false
因此,ECMAScript定义了isNaN()
函数,用来确定参数是否为NaN
。
该函数接受到值后,会尝试将该值转换为数值,任何不能被转换为数值的值都会导致这个函数返回true。
alert(isNaN(NaN)); //true
alert(isNaN(0)); //false
alert(isNaN("Hello")); //true, "Hello"不能被转换为数值。
alert(isNaN(isNaN(NaN))) //false
数值转换
有三个函数,可以把非数值转换为数值。
-
Number()
,将任何数据类型转换为整型数值。 -
parseInt()
,将字符串转为整型数值。 -
parseFloat()
, 将字符串转为浮点型数值。
Number()
转换规则如下:
-
Boolean
类型,true
和false
被转换为1
和0
。 - 数字类型,只是简单的传入和返回。
-
null
,返回0
。 -
undefined
,返回NaN
。 - 字符串遵循以下规则:
- 如果字符串中只包含数字,则将其转换为十进制数。
- 如果字符串中包含有效的浮点数格式,则转换为相应的浮点数值。
- 如果字符串中包含有效的16进制格式,则转换为相同大小的10进制数值。
- 如果字符串为
""
,返回0。 - 如果字符串中包含上述格式之外的字符,则转换为
NaN
。
- 如果是对象,则调用对象的
valueOf()
方法,然后依照前面的规则转换返回的值。如果转换的结果是NaN,则调用对象的toString()
方法,然后再依照前面的规则转换返回的字符。
var num1 = Number("1111"); //1111
var num2 = Number(true); //1
var num3 = Number(""); //0
var num4 = Number("123a"); //NaN,因为包含字母a
var num5 = Number("0xf"); //15
相比较Number()
函数,parseInt()
函转换规则就宽松多了,parseInt()
函数在转换字符串时,更多的是看其是否符合数值模式。
它会忽略字符串前面的空格,直至找到第一个非空格字符。
如果第一个字符不是负号或数字,那么parseInt()
函数会返回NaN
。
如果第一个字符是数字,parseInt()
函数会继续解析第二个字符,直到解析完成,或者遇到非数字字符。
如果字符串以0x
开头,parseInt()
函数会将其当作16进制整数。
var num1 = parseInt(" 123"); //123
var num2 = parseInt("123a"); //123
var num3 = parseInt(""); //NaN
var num4 = parseInt("0xf"); //15
var num5 = parseInt("07"); //ECMAScript3中返回56,ECMAScript5以上返回7
在使用parseInt()
函数解析八进制字面值数值时,ECMAScript3和ECMAScript5存在分歧,为了消除上述困惑,可以为这个函数提供第二个参数:转换时的基数。
如果知道当前字符串是16进制,那么可以指定基数为16,例子如下:
var num1 = parseInt("f",16); //15
var num2 = parseInt("70",8); //56
var num3 = parseInt("10",2); //2
不指定基数意味着让parseInt()
函数决定如何解析输入的字符串,为了避免错误解析,强烈建议无论在什么情况下都明确指定基数。
parseFloat()
函数与parseInt()
函数类似,也是从第一个字符开始解析每一个字符,而且也是一直解析到字符串末尾,或者解析遇到了一个无效的浮点数字符为止。
parseFloat()
函数会始终忽略前导的0
。由于parseFloat()
函数只解析10进制数,因此它没有第二个参数指定基数的用法。
如果字符串包含的是一个可解析为整数的数,parseFloat()
函数会返回整数。
var num1 = parseFloat("1234abcd"); //1234,解析到整数值,返回整数1234
var num2 = parseFloat("0xA"); //0,遇到x无效字符,返回0
var num3 = parseFloat("22.5"); //22.5
var num4 = parseFloat("22.34.5"); //22.34,遇到.无效字符,返回22.34
var num5 = parseFloat("0908.5"); //908.5,忽略前导0,返回908.5
var num6 = parseFloat("3.125e7"); //31250000
String类型
String
类型用于表示零或多个16位Unicode
组成的字符序列,即字符串。
通常有两种表示方法。(ECMAScript6中,新增一种表示方法)
var firstName = "Nicholas";
var lastName = 'Zakas';
单引号表示的字符串与双引号表示的字符串完全相同,但双引号开头必须双引号结尾,单引号开头必须单引号结尾。
字面值常量
String
类型包含一些特殊的字符字面值,也叫转义序列,用于表示非打印字符,或其它用途的字符,这些字面值如下表所示:
字面量 | 含义 |
---|---|
\n | 换行 |
\t | 制表 |
\b | 空格 |
\r | 回车 |
\f | 进纸 |
\\ | 斜杠 |
\' | 单引号' |
\" | 双引号" |
\xnn | 以16进制代码nn表示字符,\x41表示"A" |
\unnnn | 以十六进制代码nnnn表示一个Unicode字符,\u03a3表示希腊字母 |
上述字符字面值可以出现在字符串中任意位置,而且也作为一个字符被解析。
var text = "This is the letter sigma: \u03a3.";
alert(text.length); //28
如果字符串中包含双字节字符,那么length
属性可能不会精确返回字符串中字符的数目。
字符串的特点
ECMAScript中的字符串是不可变的,也就是说,字符串一旦创建,他们的值就不能改变。
要改变某个变量保存的字符串,首先得先销毁原来的字符串,再用另一个新字符串填充该变量。
var str = "Hello";
str = str + " World!"; // Hello World!
转换为字符串
有两种方式可以将一个值转换为字符串:
除了null
和undefined
之外,每个值都有的toString()
函数。
var x = 100;
var xString = x.toString(); // "100"
var y = true;
var yString = y.toString(); // "true"
大多数情况下,toString()
函数不必传递参数,但在调用数值的toString()
函数时,可以传递一个参数:输出值的基数。
var num = 10;
var numString1 = num.toString(); // "10"
var numString2 = num.toString(2); // "1010"
var numString3 = num.toString(8); // "12"
var numString4 = num.toString(10); // "10"
var numString5 = num.toString(16); // "a"
在不知道值是否为null
或undefined
时,还可以使用转型函数String()
,这个函数能够将任何类型的值转换为字符串。
String()
函数遵循下列转换规则:
- 如果值有
toString()
函数,则调用该方法,并返回相应的结果。 - 如果值是
null
,则返回"null"
。 - 如果值是
undefined
,则返回"undefined"
。
var v1 = 123;
var v2 = true;
var v3 = null;
var v4;
alert(String(v1)); // "123"
alert(String(v2)); // "true"
alert(String(v3)); // ”null“
alert(String(v4)); // "undefined"
Object类型
ECMAScript中的对象其实就是一组数据和功能的集合。对象可以通过执行new
操作符后跟要创建的对象名称来创建。
var o = new Object();
这个语法与Java中创建对象的语法相似,但在ECMAScript中,如果不给构造函数传递参数,则可以省略后面的那对圆括号。(不推荐此做法)
在ECMAScript中,Object
类型是所有它的实例的基础,换句话说,Object
类型所具有的任何属性和方法也同样存在更具体的对象中。
Object
的每个实例都有下列属性和方法。
-
Constructor
,保存着用于创建当前对象的函数。 -
hasOwnProperty(propertyName)
,用于检查给定的属性在当前实例中是否存在,其中propertyName
参数必须以字符串形式指定。 -
isPrototypeOf(object)
,用于检查传入的对象是否是另一个对象的原型。 -
propertyIsEnumerable(propertyName)
,用于检查给定的属性是否能使用for-in
语句来枚举。 -
toLocaleString()
,返回对象的字符串表示,该字符串与执行环境地区相对应。 -
toString()
,返回对象的字符串表示。 -
valueOf()
,返回对象的字符串,数值或布尔值表示。通常与toString()
方法的返回值相同。
从技术角度来说,ECMA-262中对象的行为不一定适用于JavaScript中的其他对象。浏览器中的对象,比如BOM和DOM中的对象,都属于宿主对象,因为它们是由宿主实现提供和定义的。
总结
本文总结分为如下三大部分,以下总结不知道原理的,评论区见。
与C++/Java不同之处
- JavaScript只有6种数据类型(
Number
,Boolean
,Object
,Undefined
,Null
,String
),且不支持用户自定义类型。 - JavaScript中当计算溢出时,结果会为正或负
Infinity
。 - JavaScript中有一个神奇的值
NaN
。
严格模式
- 在严格模式下,不能定义以八进制为字面值表示整数,会导致引擎抛出错误。
Effective小技巧
- 强烈建议,定义变量时,显式的将其初始化。(为什么?)
- 强烈建议,任何情况下,定义变量时,都不要将其初始化为
undefined
。(为什么?) - 强烈建议,定义要保存对象的变量时,将其初始化为
null
。(为什么?) - 强烈建议,使用
parseInt()
函数,而不是Number()
函数。 - 强烈建议,使用
parseInt()
函数时,明确指定基数。
网友评论