《JavaScript面向对象编程指南》——2.3 基本数据类型

    xiaoxiao2024-02-01  146

    本节书摘来自异步社区《JavaScript面向对象编程指南》一书中的第2章,第2.3节,作者: 【加】Stoyan Stefanov 译者: 凌杰 更多章节内容可以访问云栖社区“异步社区”公众号查看。

    2.3 基本数据类型

    我们在程序中所使用的任何值都是有类型的。在JavaScript中,主要包含以下几大基本数据类型。

    1.数字——包括浮点数与整数,例如1、100、3.14。

    2.字符串——一序列由任意数量字符组成的序列,例如"a"、"one"、"one 2 three"。

    3.布尔值——true或false。

    4.undefined——当我们试图访问一个不存在的变量时,就会得到一个特殊值: undefined。除此之外,使用一个未初始化的变量也会如此。因为JavaScript会自动将变量在初始化之前的值设定为undefined。

    5.null——这是另一种只包含一个值的特殊数据类型。所谓的null值,通常是指没有值、空值,不代表任何东西。null与undefined最大的不同在于,被赋予null的变量通常被认为是已经定义了的,只不过它不代表任何东西。关于这一点,我们稍后会通过一些具体的示例来解释。

    任何不属于上述五种基本类型的值都会被认为是一个对象。甚至有时候我们也会将null视为对象,这会使人有些尴尬——这是一个不代表任何东西的对象(东西)。我们将会在第4章中深入阐述对象的概念,现在我们只需要记住一点,JavaScript中的数据类型主要分为以下两个部分。

    基本类型(上面列出的五种类型)。非基本类型(即对象)。2.3.1 查看类型操作符——typeof如果我们想知道某个变量或值的数据类型,可以调用一种叫做typeof的特殊操作符。该操作符会返回一个代表数据类型的字符串,它的值包括:“number”、“string”、“boolean”、“undefined”、“object”和“function”。在接下来的几节中,我们将会逐一展示对五种基本数据类型使用typeof操作符时的情况。

    2.3.2 数字最简单的数字类型当然就是整数了。如果我们将一个变量赋值为1,并对其调用typeof操作符,控制台就会返回字符串“number”,请看下面的代码。此外要注意的是,当您第二次设置变量值时,就不需要再使用var语句了。

    >>> var n = 1; >>> typeof n; "number" >>> n = 1234; >>> typeof n; "number"

    当然,这也同样适用于浮点数(即含小数部分的数字):

    >>> var n2 = 1.23; >>> typeof n; "number"

    1 除了对变量赋值以外,我们也可以直接对一个数值调用typeof。例如:

    >>> typeof 123; "number"

    2.3.2.1 八进制与十六进制当一个数字以0开头时,就表示这是一个八进制数。例如,八进制数0377所代表的就是十进制数255。

    >>> var n3 = 0377; >>> typeof n3; "number" >>> n3; 255

    如您所见,例子中最后一行所输出的就是该八进制数的十进制表示形式。如果您对八进制数还不太熟悉,那么十六进制您一定不会感到陌生,毕竟,CSS样式表中的颜色值使用的都是十六进制。

    在CSS中,我们定义颜色的方式有以下两种。

    使用十进制数分别指定R(红)、G(绿)、B(蓝)的值2,取值范围都为0~255。例如rgb(0,0,0)代表黑色、rgb(255,0,0)代表红色(红值达到最大值,而绿和蓝都为0值)。使用十六进制数,两个数位代表一种色值,依次是R、G、B。例如#000000代表黑色、#ff0000代表红色,因为十六进制的ff就等于255。在JavaScript中,我们会用0x前缀来表示一个十六进制值(简称为hex)。

    >>> var n4 = 0x00; >>> typeof n4; "number" >>> n4; 0 >>> var n5 = 0xff; >>> typeof n5; "number" >>> n5; 255

    2.3.2.2 指数表示法一个数字可以表示成1e1(或者1e+1、1E1、1E+1)这样的指数形式,意思是在数字1后面加1个0,也就是10。同理,2e+3的意思是在数字2后面加3个0,也就是2000。

    >>> 1e1 10 >>> 1e+1 10 >>> 2e+3 2000 >>> typeof 2e+3; "number"

    此外,我们也可以将2e+3理解为将数字2的小数点向右移三位。依照同理,2e-3也就能被理解为是将数字2的小数点左移三位。

    >>> 2e-3 0.002 >>> 123.456E-3 0.123456 >>> typeof 2e-3 "number"

    2.3.2.3 Infinity在JavaScript中,还有一种叫做Infinity的特殊值。它所代表的是超出了JavaScript处理范围的数值。但Infinity依然是一个数字,我们可以在控制台使用typeof来测试Infinity。当我们输入1e308时,一切正常,但一旦将后面的308改成309就出界了。经实践证明,JavaScript所能处理的最大值是1.7976931348623157e+308,而最小值为5e-324。

    >>> Infinity Infinity >>> typeof Infinity "number" >>> 1e309 Infinity >>> 1e308 1e+308

    另外,任何数除0也为infinity:

    >>> var a = 6 / 0; >>> a Infinity

    Infinity表示的是最大数(或者比最大数还要大的数),那么最小数该如何表示呢?答案是在Infinity之前加一个负号:

    >>> var i = -Infinity; >>> i -Infinity >>> typeof i "number"

    但这是不是意味着我们可以得到双倍的Infinity呢?——毕竟我们可以从0加到Infinity,也可以从0减到-Infinity。好吧,这只是个玩笑。事实上这是不可能的,因为即便将正负Infinity相加,我们也不会得到0,而是会得到一个叫做NaN(Not A Number的缩写,即不是数字)的东西。

    >>> Infinity - Infinity NaN >>> -Infinity + Infinity NaN

    而且,Infinity与其他的任何操作数执行任何算术运算的结果,都是Infinity。

    >>> Infinity - 20 Infinity >>> -Infinity * 3 -Infinity >>> Infinity / 2 Infinity >>> Infinity - 99999999999999999 Infinity

    2.3.2.4 NaN还记得之前见过的那个NaN吗?尽管该值的名字叫做“不是数字”,但事实上它依然属于数字,只不过是一种特殊的数字罢了。

    >>> typeof NaN "number" >>> var a = NaN; >>> a NaN

    如果我们在对一个假定的数字执行某个操作时失败了,就会得到一个NaN。例如,当我们试图将10与字符"f"相乘时,其结果就会为NaN,因为"f"显然是不支持乘法运算的。

    >>> var a = 10 * "f"; >>> a NaN

    而且,NaN是具有传染性的,只要我们的算术运算中存在一个NaN,整个运算就会失败。

    >>> 1 + 2 + NaN NaN

    2.3.3 字符串字符串通常指的是一组用于表示文本的字符序列。在JavaScript中,一对双引号或单引号之间的任何值都会被视为一个字符串。也就是说,1是一个数字的话,"1"就是一个字符串了。在一个字符串上,typeof操作符会返回“string”。

    >>> var s = "some characters"; >>> typeof s; "string" >>> var s = 'some characters and numbers 123 5.87'; >>> typeof s; "string"

    字符串中可以包含数字,例如:

    >>> var s = '1'; >>> typeof s; "string"

    如果引号之间没有任何东西,它所表示的依然是一个字符串(即空字符串):

    >>> var s = ""; typeof s; "string"

    之前,当我们在两个数字之间使用加号时,所执行的是加法运算。但在字符串中,这是一个字符串拼接操作,它返回的是两个字符串拼接之后的结果。例如:

    >>> var s1 = "one"; var s2 = "two"; var s = s1 + s2; s; "onetwo" >>> typeof s; "string"

    像+这样的双功能操作符可能会带来一些错误。因此,我们如果想执行拼接操作的话,最好确保其所有的操作数都是字符串。同样的,在执行数字相加时,我们也要确保其所有的操作数都是数字。至于如何做到这一点,我们将会在后续章节中详细讨论。

    2.3.3.1 字符串转换当我们将一个数字字符串用于算术运算中的操作数时,该字符串会在运算中被当做数字类型来使用。(由于加法操作符的歧义性,这条规则不适用于加法运算。)

    >>> var s = '1'; s = 3 * s; typeof s; "number" >>> s 3 >>> var s = '1'; s++; typeof s; "number" >>> s 2

    于是,将数字字符串转换为数字就有了一种偷懒的方法:只需将该字符串与1相乘即可。(当然,更好的选择是调用parseInt函数,关于这点,我们将会在下一章中介绍。)

    >>> var s = "100"; typeof s; "string" >>> s = s * 1; 100 >>> typeof s; "number"

    如果转换操作失败了,我们就会得到一个NaN值。

    >>> var d = '101 dalmatians'; >>> d * 1 NaN

    此外,将其他类型转换为字符串也有一种偷懒的方法,只需要将其与空字符串连接即可:

    >>> var n = 1; >>> typeof n; "number" >>> n = "" + n; "1" >>> typeof n; "string"

    2.3.3.2 特殊字符串在表2-2中,我们列出了一些具有特殊含义的字符串。

    除此之外,还有一些很少被使用的特殊字符,例如:b(退格符)、v(纵向制表符)、f(换页符)等。

    2.3.4 布尔值布尔类型中只有两种值:true和false。它们可用于引号以外的任何地方。

    >>> var b = true; typeof b; "boolean" >>> var b = false; typeof b; "boolean"

    如果true或false在引号内,它就是一个字符串。

    >>> var b = "true"; typeof b; "string"

    2.3.4.1 逻辑运算符在JavaScript中,主要有三种逻辑运算符,它们都属于布尔运算。分别是:

    !——逻辑非(取反)。&&——逻辑与。||——逻辑或。在JavaScript中,如果我们想描述一些日常生活中非真即假的事物,就可以考虑使用逻辑非运算符:

    >>> var b = !true; >>> b; false

    如果在同一个值上执行两次逻辑非运算,其结果就等于原值3:

    >>> var b = !!true; >>> b; true

    如果在一个非布尔值上执行逻辑运算,该值会在计算期间被转换为布尔值:

    >>> var b = "one"; >>> !b; false

    如您所见,上例中的字符串"one"是先被转换为布尔值true然后再取反的,结果为false。如果我们对它取反两次,结果就会为true。例如:

    >>> var b = "one"; >>> !!b; true

    使用双重取反操作可以很容易地将任何值转换为等效的布尔值。虽然这种方法很少被用到,但从另一个角度也说明了将其他类型的值转换为布尔值的重要性。而事实上,除了下面所列出特定值以外(它们将被转换为false),其余大部分值在转换为布尔值时都为true。

    空字符串""nullundefined数字0数字NaN布尔值false这6个值有时也会被我们统称为falsy,而其他值则被称为truthy(包括字符串"0"、""、"false")。

    接下来,让我们来看看另外两个操作符——逻辑与和逻辑或的使用示例。当我们使用逻辑与操作符时,当且仅当该操作所有操作数为true时,它才为true。而逻辑或操作则只需要至少一个操作数为true即可为true。

    >>> var b1 = true; var b2 = false; >>> b1 || b2 true >>> b1 && b2 false

    在表2-3中,我们列出了所有可能的情况及其相应结果。

    当然,我们也能连续执行若干个逻辑操作。例如:

    >>> true && true && false && true false >>> false || true || false true

    我们还可以在同一个表达式中混合使用&&和||。不过在这种情况下,我们最好用括号来明确一下操作顺序。例如:

    >>> false && false || true && true true >>> false && (false || true) && true false

    2.3.4.2 操作符优先级您可能会想知道,为什么上例中的第一个表达式(false && false || true && true)结果为true。答案在于操作符优先级。这看上去有点像数学,例如:

    >>> 1 + 2 * 3 7

    由于乘法运算的优先级高于加法,所以该表达式会先计算2* 3,这就相当于我们输入的表达式是:

    > >>> 1 + (2 * 3) 7

    逻辑运算符也一样,!的优先级最高,因此在没有括号限定的情况下它将会被最先执行。然后,接下来的优先顺序是先&&后||。也就是说:

    >>> false && false || true && true true

    与下面表达式等效:

    >>> (false && false) || (true && true) true

    最佳方法:

    尽量使用括号,而不是依靠操作符优先级来设定代码的执行顺序,这样我们的代码才能有更好的可读性。2.3.4.3 惰性求值如果在一个连续的逻辑操作中,操作结果在最后一个操作完成之前就已经明确了的话,那么该操作往往就不必再继续执行了,因为这已经不会对最终结果产生任何影响。例如,在下面这种情况中:

    >>> true || false || true || false || true true

    在这里,所有的逻辑或运算符优先级都是相同的,只要其中任何一个操作数为true,该表达式的结果就为true。因而当第一个操作数被求值之后,无论后面的值是什么,结果都已经被确定了。于是我们可以允许JavaScript引擎偷个懒(好吧,这也是为了提高效率),在不影响最终结果的情况下省略一些不必要的求值操作。为此,我们可以在控制台中做个实验:

    >>> var b = 5; >>> true || (b = 6) true >>> b 5 >>> true && (b = 6) 6 >>> b 6

    除此之外,上面的例子还向我们显示了另一个有趣的事情——如果JavaScript引擎在一个逻辑表达式中遇到一个非布尔类型的操作数,那么该操作数的值就会成为该表达式所返回的结果。例如:

    >>> true || "something" true >>> true && "something" "something"

    通常情况下,这种行为是应该尽量避免的,因为它会使我们的代码变得难以理解。但在某些时候这样做也是有用的。例如,当我们不能确定某个变量是否已经被定义时,就可以像下面这样,即如果变量mynumber已经被定义了,就保留其原有值,否则就将它初始化为10。

    var mynumber = mynumber || 10;

    这种做法简单而优雅,但是请注意,这也不是绝对安全的。如果这里的mynumber之前被初始化为0(或者是那6个falsy值中的任何一个),这段代码就不太可能如我们所愿了。

    2.3.4.4 比较运算符在JavaScript中,还有另外一组以布尔值为返回值类型的操作符,即比较操作符。下面让我们通过表2-4来了解一下它们以及相关的示例。

    还有一件有趣的事情要提醒读者注意:NaN不等于任何东西,包括它自己。

    >>> NaN == NaN false

    2.3.5 undefined与null通常情况下,当我们试图访问某个不存在的或者未经赋值的变量时,就会得到一个undefined值。JavaScript会自动将声明时没有进行初始化的变量设为undefined。

    当我们试图使用一个不存在的变量时,就会得到这样的错误信息:

    >>> foo foo is not defined

    这时候,如果我们在该变量上调用typeof操作符,就会得到字符串“undefined”:

    >>> typeof foo "undefined"

    如果我们声明一个变量时没有对其进行赋值,调用该变量时并不会出错,但typeof操作符依然会返回“undefined”。

    >>> var somevar; >>> somevar >>> typeof somevar "undefined"

    而null值就完全是另一回事了。它不能通过JavaScript来自动赋值,只能通过我们的代码来完成。

    >>> var somevar = null null >>> somevar null >>> typeof somevar "object"

    尽管undefined和null之间的差别微乎其微,但有时候也很重要。例如,当我们对其分别执行某种算术运算时,结果就会截然不同:

    >>> var i = 1 + undefined; i; NaN >>> var i = 1 + null; i; 1

    这是因为null和undefined在被转换为其他基本类型时,方法存在一定的区别,下面我们给出一些可能的转换类型。

    转换成数字:

    >>> 1*undefined NaN >>> 1*null 0

    转换成布尔值:

    >>> !!undefined false >>> !!null false

    转换成字符串:

    >>> "" + null "null" >>> "" + undefined "undefined" 相关资源:JavaScript高级程序设计
    最新回复(0)