JavaScript--变量与基本数据类型

前言
JavaScript中的变量为松散类型,所谓松散类型就是指当一个变量被申明出来就可以保存任意类型的值,就是不像SQL一样申明某个键值为int就只能保存整型数值,申明varchar只能保存字符串。一个变量所保存值的类型也可以改变,这在JavaScript中是完全有效的,只是不推荐。相比较于将变量理解为“盒子“,《JavaScript编程精解》中提到应该将变量理解为“触手”,它不保存值,而是抓取值。这一点在当变量保存引用类型值时更加明显。

JavaScript中变量可能包含两种不同的数据类型的值:基本类型和引用类型。基本类型是指简单的数据段,而引用类型指那些可能包含多个值的对象。本文主要介绍基本数据类型及其特点。

基本类型包括:Null、Undefined、Number、String、Boolean。引用类型主要包括:Object、Array、Date、RegExp、Function。

申明
JavaScript中申明变量通过var操作符,申明的变量会成为其所在作用域内的局部变量,意思就是在全局申明的变量就是通常所说的全局变量,在函数内申明的变量就是以该函数为作用域的局部变量,局部变量会在函数执行完毕后被销毁,未通过var操作符申明的变量会默认为全局变量。需要一次申明多个变量时可以通过单var操作符的方式,代码会更加简洁。

var name = 'susan',
    age = '23',
    sex = 'female';

typeof操作符
在介绍基本类型值之前,先说下typeof操作符,typeof操作符会返回数据类型的字符串表示。用它来检测基本数据类型比较有效率,而检测引用类型时通常用instanceof操作符。

typeof undefined; //undefined
typeof 2015; //number
typeof false; //boolean
typeof null; //object
typeof 'abc'; //string
typeof {a:1}; //object

这里有一点不同的是,typeof在对null进行检测时会返回字符串“object”,因为在JavaScript中null被当作空对象指针,这一点在Douglas的《JavaScript语言精粹》也被吐槽过,不过了解下就可以了。

Undefined类型
Undefined类型只有一个特殊值即undefiend。所有未初始化的变量均会保存该值。

var aa;
alert(aa); //undefined

这里要注意一点,undefined与未定义的变量不同,如果在代码中调用某个未定义(申明)的变量,解析器会提示如下信息。

意为这个变量没有被申明过,查找的方式是通过沿作用域链向上搜索,如果在全局环境中都没有找到该变量的申明则抛出错误,这部分内容本菜以后和大家讨论。

Null类型
Null类型同样也只包含一个值即null,从逻辑上看它被当作空对象指针,正是由于这个特性,如果你定义某个变量时不确定当前赋何值,但未来需要赋某个object类型值时,正确的方式就是将该变量初始化为null。

这里提一句,在对null与undefined进行==比较时,会返回true,据《JavaScript高级程序设计》说,undefined派生自null,所以ECMA-262规定它俩相等性操作为true。

Boolean类型
Boolean俗称布尔,仅包括两个值:true和false。这里有一个Boolean()转型函数,它可以对任意类型的值使用,作用就是将其它类型值转换为布尔型。转换规则主要如下。

String型:非空字符串-true,空字符串("")-false

Number型:任何非0数-true,0与NaN-false

Object型:任何对象-true,null-false

Undefined型:false

但并非使用该转型函数才会使数据类型转换,当遇到if语句时会对数据进行自动的类型转换。自动类型转换有其优点也有弊端,这里不再扩展。重要的是通过Boolean转型函数理解转换规则,以便在编码中使用。

这里举个非常简单的例子:在某个app中需要通过检测本地是否缓存了用户ID来判断需不需要登录操作。

if (!localStorage['memberId']) {
   //登陆操作    
}

这里当本地没有用户ID时,localStorage值为undefined,转换后为false值,非运算后为true,执行登录操作。而不需要写成localStorage['memberId'] === undefined等等。

Number类型
JavaScript中的Number类型支持十进制、八进制以及十六进制的数值。关于浮点型的数值这里有几点要注意,在JavaScript中,0.1与.1相同,但是这种省略的写法是不推荐的。由于保存浮点型所需的内存是整型的两倍,所以JavaScript会在适当的时候将不必要的浮点型转换为整型,比如浮点型的10.0会自动保存为整型的10。特别需要注意的一点是,浮点型运算精度远不如整型,例子如下:

console.log(0.1 + 0.2);

可以看到,运算并没有得到预期的结果,所以在实际运算中要注意这一点,同时这个例子也反映出了JavaScript中浮点型的最高精度即为显示的17位小数。过大或过小的数可以使用科学计数法e来表示,这一点就不再赘述。

Infinity
JavaScript能够保存的数值并不是无限大小的,当大于或小于某个界限时,该值会被自动转换为特殊值——Infinity,Infinity也包括正负两种。检测一个数值是否为Infinity可以通过isFinite()函数。

NaN
在Number类型中还有个很特殊的值,那就是NaN,即非数值(Not a Number)。这个特殊值的存在是为了避免在某些需要返回数值时因为运算问题未返回数值报错,影响程序运行。比如一个数除以0,在其他编程语言中会抛出错误,而在JavaScript中会返回NaN。

NaN有两个特点:1.任何涉及NaN的操作均会返回NaN,2.NaN不与任何值相等,包括他自己=.=,即做NaN == NaN的相等性验证时会返回false。

检测一个值是否为NaN可以用isNaN()函数,它会尝试将接收的参数转换为数值,意思就是字符串“10”可以被转换成数值10,而字符串“color”不行。转换成功返回false,反之为true。

数值转换
Number类型的数值转换方式可能通过三个函数:Number()、parseInt()、parseFloat()。由于Number()转换函数转换规则奇葩(复杂且不合理),所以这里主要介绍parseInt()与parseFloat()。

首先申明一点,parseInt()与parseFloat()函数是专门用于把字符串转换成数字的。这一点可能会导致困惑,明明是用来转换数值的,为什么要接收字符串。举个简单的例子,parseInt()在接收3.14这个浮点型数值时,会自动转换成该值的字符串表示——“3.14”,它会把3.14转换为3从逻辑上来看并不是它真的能对数值取整,而是在解析“3.14”这个字符串时遇到小数点“.”这个不能转换为数值的字符时会自动省略后面的东西。

有了以上的认识,我们来了解这两个函数具体的转换规则:

parseInt()函数在转换字符串时,会忽略前面的空格,直到找到第一个非空字符。如果第一个非空字符不是数字字符或者负号则返回NaN。如果第一个字符是数值字符会继续解析第二个,直到解析完整个字符串或者遇到了一个非数值字符(如上面3.14的例子)。

parseInt(""); //NaN
parseInt(3.14); //3
parseInt("4.12"); //4
parseInt("xyx123"); //NaN
parseInt("123xyx"); //123

parseInt()同样可以解析二进制、八进制与十六进制的数值,由于ECMAScript版本不同对非十进制数解析时会出现分歧,所以最好传入第二个参数作为基数。

parseInt(100111,2); //39
parseInt(123,8); //83
parseInt("0xBC",16); //188

与parseInt()函数类似,parseFloat()也是从第一个字符开始解析,直到字符串末尾或者遇到一个无效的浮点数字字符为止。比如,第一个小数点是有效的,第二个是无效的,因此后面的字符会被忽略。与parseInt()不同的是它始终会忽略开头的0,且不具备传入基数的能力,即只能解析十进制数值。

parseFloat("123xyx"); //123
parseFloat("xyx123"); //NaN
parseFloat("012.3"); //12.3
parseFloat("34.5"); //34.5
parseFloat("34.5.6"); //34.5

String类型
在JavaScript中字符串使用单、双引号没有区别,只是要注意起始与结束保持一致即可。JavaScript中也有转义字符,与其他语言基本一致,这里就不再赘述了。任何字符串都可以通过length属性来获取其长度。

var str = 'Hello World';
alert(str.length); //11

这里简要说一个特点,ECMAScript中字符串一旦创建了就不能被改变,例如拼接某两个字符串,首先是创建一个新的字符串,将原有的字符串组合后装入其中,最后销毁原来的两个字符串。所以并不是像看上去那样进行简单的拼接。

字符串转换
要将一个值转换为字符串类型有两个方式:1.toString()方法,2.String()转型函数。这两个方法的区别就是null,undefined值没有toString()方法,而任何类型值都可以使用String()函数。

var num = 123;
num.toString(); //"123"
var boo = false;
boo.toString(); //"false"

多数情况下,调用toString()方法不必传递参数。当要确定输出数值的不同进制时,可以传入一个基数。

var num = 10;
num.toString(); //"10"
num.toString(2); //"1010"
num.toString(8); //"12"
num.toString(10); //"10"
num.toString(16); //"a"

在不知道要转换的值是不是null或undefined时,可以使用String()方法。其规则为:如果该值有toString()方法则调用该方法,如果是null或undefined则返回其字符串表示.....好吧,总之用String()转型函数就不会错。

String(10); //"10"
String(true); //"true"
String(null); //"null"
String(undefined); //"undefined"

相关推荐