JS中数据类型分为2种:基本数据类型和复杂数据类型(引用数据类型)。
【判断数据类型】typeof和instanceof;拓展isFinite();isNaN();Array.isArray()
1.对一个值使用typeof操作符可能的结果:
"undefined":这个值未定义,是undefined值。可能是未定义的变量,也可能是声明了但没有初始化的变量,当然可能是其他值为undefined的值。
"boolean":布尔值。
"string":字符串。
"number":数值。
"object":对象,或者null值。
"function":这个值是函数。
【基本数据类型】
1. Undefined类型,只有一个取值:undefined。typeof结果为undefined。
使用var声明但未对其初始化的变量,其取值就是undefined。
undefined这个值出现的主要目的是用于比较。
注意:值为undefined的变量与未定义的变量是不一样的。未定义的变量只能执行一项操作,即typeof操作符检测类型,在非严格模式下,delete一个未定义变量不会出错,但没有意义(严格模式下出错)。
var message;//声明而未初始化
alert(message);//“undefined”。声明而未初始化的变量,值未undefined。
alert(age);//产生错误。在这之前没有定义过,出错。
alert(typeof age);//"undefined"。
显式地给变量初始化一个不是undefined值的做法是很有意义的,这样我们就可以用typeof确定变量是否被声明(因为声明了的都显式赋值了,故typeof得到undefined的变量是未声明的变量)。
2.Null类型,只有一个取值:null。typeof结果为object。instanceof检测结果是false。
null被认为是一个空的对象引用。
从逻辑角度讲,null值表示一个空的对象指针,所以typeof检测结果为object。但是Null又是一个基本数据类型,故instanceof检测的结果是false。
undefined其实是派生自null的,所以null与undefined使用相等操作符(==)总是返回true;但是undefined与null的用途完全不同,所以使用全等操作符(===)时返回false。
3.Boolean类型,只有两个取值:true,false(区分大小写)。
注意:true和false与数字值不是一回事,true不一定等于1(也可能是其他非零数字值,还可能是无穷大),false也不一定等于0(也可能是NaN)。
其他类型的值都可以转换成Boolean类型,通过调用Boolean()函数即可,转换规则如下:
Undefined类型:undefined值使用Boolean()函数后转换为false(这个类型只有一个取值,只能转换为false);
Null类型:null值用Boolean()转换为false(这个类型只有一个取值,只能转换为false);
Number类型:任何非零数字值(包括无穷大)转换为true,0和NaN转换为false;
String类型:任何非空字符串转换为true,空字符串转换为false;
Object类型:任何对象转换为true(这里说的不含null,它只是逻辑上是空对象指针,但形式上还是基本数据类型)。
4.Number类型。isFinite();isNaN();toFixed();Number();parseInt();parseFloat()。
Number类型关注以下几点:(1).数值范围;(2).NaN;(3). 整数;(4)浮点数值;(5).数值转换。
(1).数值范围。
JS能保存的最小数值保存在Number.MIN_VALUE,最大数值保存在Number.MAX_VALUE。大多数浏览器中最小值是5e-324;最大值是1.7976931348623157e+308。
比最小值更小的数值(溢出)自动被转换成-Infinity值,返回Number.NEGATIVE_INFINITY中存的值;比最大值更大的数值(溢出)自动被转换成Infinity值,返回Number.POSITIVE_INFINITY中存的值。
isFinite()用于判断数值是否在最小值与最大值之间,若是则返回true,否则返回false。
(2).NaN。
Not a Number,NaN是一个特殊的数值,用来表示本来要返回数值的操作数未返回数值的情况(就不会抛出错误了)。任何数值除以非数值会返回NaN。
NaN有两个特点:任何涉及NaN的操作都会返回NaN;任何值与NaN都不相等,包括NaN本身与NaN也不相等。
isNaN()用于判断值是否为NaN。该函数接受一个参数,可以是任何类型,函数会先将它转换成数值,然后再判断。是NaN返回true;不是NaN返回false。
(3).整数。
JS整数数值可以用十进制、八进制、十六进制表示。
八进制表示时首个数字为0,若后面的数字有超出7的则视为八进制表示无效,认为其为十进制数,且忽略先导0。
(4).浮点数值。
浮点数值必须包含一个小数点,些小数点后面至少有一个数字。
由于浮点数值需要的内存空间是整数的两倍,所以能转换成整数时JS会将其转换为整数保存。例如小数点后面没有数字或数字都为0时转换为整数保存。
JS讲小数点后带有6个零以上的浮点数值转换为科学记数法,如0.0000003转换为3e-7或3E-7。
浮点数最高精度是17位小数。计算时存在舍入误差,导致测定浮点数值。例如,
if(a+b==0.3){
alert("You got 0.3");
}
这个例子中,如果a=0.1,b=0.2,则 (a+b)==0.3结果是false,因为数值由二进制表示,有限位数无法精确表示0.1,存在舍入误差。但是如果a=0.05(1/20呀,可以精确表示出来),b=0.25(1/4,可以精确表示出来),则a+b=0.3返回true。
总之,不要测定某个浮点数的值,如果非得比较,那么两个思路:
第一种,把小数换为整数计算。在知道小数位数的情况下,把浮点数值扩大10的幂次倍转换为整数进行计算,然后再缩小相应倍数返回结果,如 7*0.8 改为 7*(0.8*10)/10。不知道小数位数的话,就只能改写浮点运算函数了(参考http://www.cnblogs.com/eedc/p/6628645.html)。
第二种,用toFixed()舍入位数再计算。例如,前例的 a+b==0.3 改为 (parseFloat(a+b).toFixed(2) == 0.3.toFixed(2))。
(5). 数值转换。Number();parseInt();parseFloat()。第一个用于转换任何数据类型。后两个专用于转换字符串。这三个函数对同样的输入,可能有不同的结果。
任何数据类型都可以用Number()转换成数值。Number()转换规则:
undefined:NaN。
null:0。
Boolean类型:true转换为1,false转换为0。
数值类型:就是本身啦。
字符串类型:如果字符串只包含数字和正负号,则转换为十进制整数值,且忽略前导0;如果字符串为有效的十六进制格式(0x或0X打头,后面为有效十六进制数0-9,a-f,A-F),则转换为同等大小的十进制整数值;如果字符串为有效的浮点格式(只有一个小数点,其他为数字或正负号),则转换为浮点数值,且忽略前导0;如果字符串是空的,则转换为0;如果包含上述格式之外的字符,则转换为NaN。
对象类型:调用valueOf()转换,然后再转换。若这样转换后结果为NaN,则调用toString()转换原对象,再转换。
parseInt(),只用于处理字符串,解析整数值的方式来转换,具体如下:
忽略字符串前面的空格,直到找到第一个非空格字符。
如果第一个字符不是数字或负号,返回NaN。(注意,对于空字符串,第一个也不是数字或负号,所以parseInt()返回NaN。不同于Number()。)
如果第一个字符是数字或负号,则继续解析,直到遇到第一个非数字字符(包括小数点)。parseInt("123.3")转换为123,"123hhh"转换为123。
如果字符串为有效的十六进制整数形式,parseInt()也识别的。特别的,ES3中parseInt()识别八进制("070"转换为56),但是ES5中parseInt()不识别八进制("070"转换为70,忽略了前导0)。
其实,parseInt()接受两个参数,而且推荐两个参数。第一个参数为字符串,第二个参数为基数。意思是按照基数来转换字符串,但是最终结果都返回十进制的整数值。例如:
parseInt("0x345",16);//转换为837
parseInt("345",16);//转换为837
parseInt("00x345",16);//转换为0。注意,00x不是十六进制的前缀,所以转换的时候是0
parseInt("0x345sehh",16);//转换为837
parseInt("0x345",16);//转换为837
parseInt("0x34sr",7);//转换为0
parseInt("34sr",7);//转换为25
parseFloat(),只用于转换字符串,只有一个参数,与parseInt()一个参数时的用法类似,只有些微区别:第一个小数点有效,第二个起的小数点无效;parseFloat()只解析十进制数,所以"0x12"将被parseFloat()解析为0。
如果parseFloat()解析的是一个可以存为整数值的数值(没有小数点或小数点后全为0),当然转为整数更省存储空间。
5.String类型。
JS中单引号和双引号表示的字符串没有区别,只不过单双引号必须成对,不能(" ')前面双引号,后面单引号。
任何字符串的长度都可用 length属性访问(是属性,不是方法,所以不用在后面跟小括号)。例如:
var text="test letter: \u03a3.";//字符串中有三个空格,转义字符\u03a3表示一个希腊字母。
alert(text.length);//输出15,转义字符虽然由6个字符表示,但只是一个希腊字母,故length将它算作一个字符。
字符串的特点:字符串是不可变的。当创建一个字符串(如"Java")时,在内存中开辟一段存储空间(地址A)存它。若var text="Java"其实是text中存的是存字符串的地址,即地址A。text=text+"Script"表示的是text中的地址存的内容最后变为"JavaScript"了。“字符串不可变"的含义是,不可能直接把地址A中的内容改为“JavaScript”,只能另外开辟一段存储空间(地址B)存储字符串 “JavaScript”,然后把地址A的字符串销毁,再把text中的地址改为地址B。这样,原字符串不可改变,只能另外新建字符串、销毁原字符串、更改变量指向的地址。
字符串转换有两种方法:toSting()和Sting()方法。
toString()方法只能转换布尔、数值、字符串、对象类型的数据,不能转换null和undefined类型。
在转换数值类型的数据时,toString()方法还可接受参数,参数表示数值的基数。(未指定参数时默认为转换成十进制字符。)
注意,toString()再转换负值时,转换结果是在绝对值前面加个负号,而不是转换成补码的形式。
var num=-18;
num.toString(2);//"-10010"
var num=10;
num.toString();//"10"
num.toString(2);//"1010"
num.toString(16);//"a"
String()方法可以转换任何类型的数据,但是不接收参数(数值类型转换时都是转换成十进制)。String()规则如下:
如果值有toString()方法,则用不加参数的toString()方法;
如果值为null,则返回"null";
如果值为undefined,则返回"undefined"。
转义字符:
\n换行
\t制表符
\b空格
\r回车
\f换页符
\\反斜杠
\'单引号
\"双引号
\0nnn八进制代码nnn表示的字符(n是 0-7 中的一个八进制数字)
\xnn十六进制代码nn表示的字符(n是0-F或0-f中的一个十六进制数字)
\unnnn十六进制代码nnnn表示的 一个Unicode 字符(n是0-F或0-f中的一个十六进制数字)
【复杂数据类型】
对象是一组数据和功能的集合。对象可通过new操作符创建。
引用数据类型
每个对象的实例都具有下列属性和方法:
(1).constructor:保存创建当前对象的构造函数。如var o=new Object();则o.constructor中存的是Object()函数。
(2).isPrototypeOf(object):检测object对象是否为当前对象的原型。
(3).hasOwnProperty(propertyName):检测属性propertyName是不是在当前对象实例中(当前对象实例,而不是指在实例原型)。propertyName必须为字符串形式,如o.hasOwnProperty("name")。
(4).propertyIsEnumerable(propertyName):检测属性propertyName是否可以用for-in进行枚举。propertyName必须为字符串形式。
(5). toLocaleString():返回与执行环境地区对应的字符串表示。
(6). toString():返回对象的字符串表示。
(7). valueOf():返回对象的字符串、数值或布尔值表示。
每个对象都是基于一个引用类型创建的,这个引用类型可以是JS原生的引用类型,也可以是开发人员定义的类型。