JavaScript变量与数据类型详解
变量
变量来源于数学,是计算机语言中能储存计算结果或能表示值抽象概念。变量可以通过变量名访问。
变量的作用就是用于存储值。
语法:
声明变量时,总是以关键字var
打头。任何情况下都应该这样做。然后给变量指定名称。在声明变量时,也可以给它赋值,方法是在变量名后面加上等号和值。赋值语句总是以分号结束。
var 变量名;
//或
var 变量名 = 值;
说明:尽管省略关键字var
,JavaScript也不会报错,但是这会导致变量变成全局变量
,在JavaScript使用全局变量并不是一个好习惯。分号也不是必须的,但是加上分号可读性更好,同时也能避免代码压缩时出错。
示例:
var msg;
var age = 20;
var sex = 'Male';
var isReal = true;
JavaScript的变量是松散类型的,在JavaScript中声明变量无需指定数据类型,它可以用来保存任何类型的数据。正是由于定义变量时无需指定类型,所以在JavaScript中变量的类型并不是固定的,比如上面的isReal变量本来是布尔型的,但是你也可以再把一个字符串赋给isReal变量,如isReal = "ABC";
,所以说,变量仅仅是一个用于保存值的占位符。
对于未赋值的变量,系统会默认给一个undefined
值,上面示例中的msg的值就是undefined
。
变量的数据类型
ECMAScript中有5种基本数据类型和1种引用类型。
基本数据类型:
undefined, null, boolean, number, string
引用数据类型:
object
typeof操作符
鉴于ECMAScript是松散类型的,因此需要有一种手段来检测给定变量的数据类型——typeof 就是负责提供这方面信息的操作符。对一个值使用 typeof 操作符可能返回下列某个字符串:
- "undefined"——如果这个值未定义;
- "boolean"——如果这个值是布尔值;
- "string"——如果这个值是字符串;
- "number"——如果这个值是数值;
- "object"——如果这个值是对象或 null;
- "function"——如果这个值是函数。
下面是几个使用 typeof 操作符的例子:
var msg = "itbsl";
alert(typeof msg); //string
alert(typeof(msg)); //string
alert(typeof 25); //number
这几个例子说明,typeof 操作符的操作数可以是变量(msg),也可以是数值字面量。注意,typeof 是一个操作符而不是函数,因此例子中的圆括号尽管可以使用,但不是必需的。
有些时候,typeof 操作符会返回一些令人迷惑但技术上却正确的值。比如,调用 typeof null
会返回"object",因为特殊值 null 被认为是一个空的对象引用。
从技术角度讲,函数在 ECMAScript 中是对象,不是一种数据类型。然而,函数也确实有一些特殊的属性,因此通过 typeof 操作符来区分函数和其他对象是有必要的。
undefined
Undefined 类型只有一个值,即特殊的 undefined。在使用 var 声明变量但未对其加以初始化时, 这个变量的值就是 undefined,例如:
var message;
alert(message == undefined); //true
这个例子只声明了变量 message,但未对其进行初始化。比较这个变量与 undefined 字面量,结果表明它们是相等的。
一般而言,不存在需要显式地把一个变量设置为 undefined 值的情况。字面值undefined 的主要目的是用于比较,而 ECMA-262 第 3 版之前的版本中并没有规定这个值。第 3 版引入这个值是为了正式区分空对象指针与未经初始化的变量。
哪些情况下的值会是undefined呢?
- 没有return语句的函数的返回值
- 未赋值的变量的值
- 稀疏数组中不存在的数组元素的值
- 访问不存在的属性的值
- 访问已删除属性的值
稀疏数组是有些索引处有值,而其他索引处没有值得数组。假设有一个长度为10的数组,在索引1000处添加一个新元素后,索引10~999处的值都是undefined。你可以这样认为,这犹如创建了989个变量,但没有对它们进行初始化。虽然这些变量没有值,但它们都要占用计算机内存,因此除非有充分的理由,否则千万不要创建稀疏数组。请注意,undefined是一个值,而不是字符串,undefined和字符串"undefined"并不是一个东西。
undefined到底是什么呢?它其实并不复杂。你可以这么认为:对于任何还没值(即还未初始化)的东西,都会将undefined赋给它。
undefined值的类型为什么是undefined?
我认为原因如下:它不是对象,不是数字、字符串或布尔值,也不是任何明确的东西。既然如此,为何不将这种类型也视为未定义的呢?这是JavaScript怪异的灰色地带之一,你不得不接受。
null
Null 类型是第二个只有一个值的数据类型,这个特殊的值是 null。从逻辑角度来看,null 值表示一个空对象指针,而这也正是使用 typeof 操作符检测 null 值时会返回"object"的原因,如下面
的例子所示:
var car = null;
alert(typeof car); //"object"
如果定义的变量准备在将来用于保存对象,那么最好将该变量初始化为 null 而不是其他值。这样一来,只要直接检查 null 值就可以知道相应的变量是否已经保存了一个对象的引用。
实际上,undefined 值是派生自 null 值的,因此 ECMA-262 规定对它们的相等性测试要返回 true:
alert(null == undefined); //true
这里,位于 null 和 undefined 之间的相等操作符(==)总是返回 true,不过要注意的是,这个操作符出于比较的目的会转换其操作数。
尽管 null 和 undefined 有这样的关系,但它们的用途完全不同。如前所述,无论在什么情况下都没有必要把一个变量的值显式地设置为 undefined,可是同样的规则对 null 却不适用。换句话说,只要意在保存对象的变量还没有真正保存对象,就应该明确地让该变量保存 null 值。这样做不仅可以体现 null 作为空对象指针的惯例,而且也有助于进一步区分 null 和 undefined。
我们在使用getElementById获取dom对象时,如果指定的id不存在,它返回的值是null,而不是undefined。null到底是什么?getElementById为何不返回undefined?
答: 在很多语言中,都有一个表示”无对象“的概念,这挺好。就拿方法document.getElementById来说吧,是不是要求它返回一个对象?如果它无法返回一个对象呢?在这种情况下,我们希望返回一个含义如下的值:要是有对象,我就会是一个对象,可当前没有。这正是null的含义。我们以后还会经常碰到将变量的值显式的设置为null,意思是说我原本要将一个对象赋给这个变量,但现在没有这样的对象。你可能挠着头说,为何不使用undefined来表达这种意思呢?很多人都这么想。原因是JavaScript刚面世时时这么想的:用一个值表示变量还未初始化,用另一个值表示没有对象可赋给变量。这并不完美,而且显得有些多余,但现实情况就是如此。你只需牢记undefined和null各自的用途,并知道下面一点就行了:在应该提供一个对象,但无法创建或找到时,将提供null;在变量未初始化、对象没有指定属性或数组没有指定元素时,将返回undefined。
boolean
Boolean 类型是 ECMAScript 中使用得最多的一种类型,该类型只有两个字面值:true 和 false。这两个值与数字值不是一回事,因此 true 不一定等于 1,而 false 也不一定等于 0。以下是为变量赋Boolean 类型值的例子:
var found = true;
var lost = false;
需要注意的是,Boolean 类型的字面值 true 和 false 是区分大小写的。也就是说,True 和 False(以及其他的混合大小写形式)都不是 Boolean 值,只是标识符。
虽然 Boolean 类型的字面值只有两个,但 ECMAScript 中所有类型的值都有与这两个 Boolean 值等价的值。要将一个值转换为其对应的 Boolean 值,可以调用转型函数 Boolean(),如下例所示:
var message = "Hello world!";
var messageAsBoolean = Boolean(message);
在这个例子中,字符串 message 被转换成了一个 Boolean 值,该值被保存在 messageAsBoolean变量中。可以对任何数据类型的值调用 Boolean()函数,而且总会返回一个 Boolean 值。至于返回的这个值是 true 还是 false,取决于要转换值的数据类型及其实际值。下表给出了各种数据类型及其对应的转换规则。
数据类型 | 转换为true的值 | 转换为false的值 |
---|---|---|
Boolean | true | false |
String | 任何非空字符串 | ""(空字符串) |
Number | 任何非零数字值(包括无穷大) | 0和NaN |
Object | 任何对象 | null |
Undefined | undefined |
这些转换规则对理解流控制语句(如if语句)自动执行相应的Boolean转换非常重要,请看下面的代码:
var message = "Hello world!";
if (message){
alert("Value is true");
}
运行这个示例,就会显示一个警告框,因为字符串 message 被自动转换成了对应的 Boolean 值 (true)。由于存在这种自动执行的 Boolean 转换,因此确切地知道在流控制语句中使用的是什么变量 至关重要。错误地使用一个对象而不是一个 Boolean 值,就有可能彻底改变应用程序的流程。
number
Number 类型应该是 ECMAScript 中最令人关注的数据类型了,这种类型使用 IEEE754 格式来表示整数和浮点数值(浮点数值在某些语言中也被称为双精度数值)。
数值范围
由于内存的限制,ECMAScript 并不能保存世界上所有的数值。ECMAScript 能够表示的最小数值保 存在 Number.MIN_VALUE 中——在大多数浏览器中,这个值是 5e-324;能够表示的最大数值保存在 Number.MAX_VALUE 中——在大多数浏览器中,这个值是 1.7976931348623157e+308。如果某次计算的 结果得到了一个超出 JavaScript 数值范围的值,那么这个数值将被自动转换成特殊的 Infinity 值。具 体来说,如果这个数值是负数,则会被转换成-Infinity(负无穷),如果这个数值是正数,则会被转 换成 Infinity(正无穷)。
如上所述,如果某次计算返回了正或负的 Infinity 值,那么该值将无法继续参与下一次的计算, 因为 Infinity 不是能够参与计算的数值。要想确定一个数值是不是有穷的(换句话说,是不是位于最 小和最大的数值之间),可以使用 isFinite()函数。这个函数在参数位于最小与最大数值之间时会返 回 true,如下面的例子所示:
var result = Number.MAX_VALUE + Number.MAX_VALUE;
alert(isFinite(result)); //false
尽管在计算中很少出现某些值超出表示范围的情况,但在执行极小或极大数值的计算时,检测监控这些值是可能的,也是必需的。
NaN
NaN,即非数值(Not a Number)是一个特殊的数值,这个数值用于表示一个本来要返回数值的操作数未返回数值的情况(这样就不会抛出错误了)。例如,在其他编程语言中,任何数值除以 0 都会导致错误, 从而停止代码执行。但在 ECMAScript 中,0除以 0 会返回 NaN,正数除以 0 返回 Infinity,负数除以 0 返回-Infinity,因此不会影响其他代码的执行。
NaN 本身有两个非同寻常的特点。首先,任何涉及 NaN 的操作(例如 NaN/10)都会返回 NaN,这个特点在多步计算中有可能导致问题。其次,NaN 与任何值都不相等,包括 NaN 本身。例如,下面的代码会返回 false:
alert(NaN == NaN); //false
针对 NaN 的这两个特点,ECMAScript 定义了 isNaN()函数。这个函数接受一个参数,该参数可以
是任何类型,而函数会帮我们确定这个参数是否“不是数值”。isNaN()在接收到一个值之后,会尝试
将这个值转换为数值。某些不是数值的值会直接转换为数值,例如字符串"10"或 Boolean 值。而任何
不能被转换为数值的值都会导致这个函数返回 true。请看下面的例子:
alert(isNaN(NaN)); //true
alert(isNaN(10)); //false(10 是一个数值)
alert(isNaN("10")); //false(可以被转换成数值 10)
alert(isNaN("blue")); //true(不能转换成数值)
alert(isNaN(true)); //false(可以被转换成数值 1)
这个例子测试了 5 个不同的值。测试的第一个值是 NaN 本身,结果当然会返回 true。然后分别测试了数值 10 和字符串"10",结果这两个测试都返回了 false,因为前者本身就是数值,而后者可以被转换成数值。但是,字符串"blue"不能被转换成数值,因此函数返回了 true。由于 Boolean 值 true可以转换成数值 1,因此函数返回false。
既然NaN(Not a Number)指的是”不是数字“,那它是什么呢?如果指出它是什么,而非它不是什么,是不是更容易理解呢?那你认为它是什么呢?为获得一点线索,可检查类型:
var test = 0/0;
console.log(typeof test); //number
到底是怎么回事儿?NaN的类型是数字?一个不是数字的东西,其类型怎么可能是数字呢?你可以这样想:NaN是一个糟糕的名称;与其称之为”不是数字“,还不如称之为”无法表示的数字“(必须承认,这样首字母缩写将不那么出色)。如果这样想,就可以认为NaN是一个数字,只是无法表示而已(至少对计算机来说如此)。
string
String 类型用于表示由零或多个 16 位 Unicode 字符组成的字符序列,即字符串。字符串可以由双引号(")或单引号(')表示,因此下面两种字符串的写法都是有效的:
var firstName = "Nicholas";
var lastName = 'Zakas';
与 PHP 中的双引号和单引号会影响对字符串的解释方式不同,ECMAScript 中的这两种语法形式没有什么区别。用双引号表示的字符串和用单引号表示的字符串完全相同。
其它类型数据和字符串进行+
操作时,会将其它类型数据转为字符串,然后同字符串拼接。
var num = 3;
var isTrue = true;
var str = "123";
var result1 = num + str;
var result2 = isTrue + str;
alert(result1); //3123
alert(result2); //true123