第一章 - 值,类型和运算符


  • administrators

    在机器表面下方,程序移动。不费吹灰之力,它会扩展和收缩。非常和谐地,电子散射并重新组合。显示器上的形体只是水面上的涟漪。本质无形地保持在下面。
    --“Master Yuan Ma ,编程之书

    在计算机世界里面,只有数据。你可以读取数据,修改数据,创建新数据, 但不能提及非数据。所有这些数据都存储为一长串的比特序列,因此它们看起来很相似。

    比特是任何一种二值的东西,通常被描述为零和一。在计算机内部,它们采取诸如高或低电荷,强或弱信号或CD表面上的闪亮或暗淡点等形式。任何一条离散信息都可以简化为零和1的序列,从而以比特表示。

    例如,我们可以用比特表示数字13。它的工作方式与十进制数相同,但不是10个不同的数字,而是只有2个,每个的权重从右到左增加2倍。以下是构成数字13的位,其下方显示的数字权重如下:

       0  0  0  0 1 1 0 1
     128 64 32 16 8 4 2 1
    

    所以这是二进制数00001101.它的非零数字代表8,4和1,加起来等于13。

    想象一下比特的 。典型的现代计算机在其易失性数据存储(工作存储器)中具有超过300亿比特。非易失性存储(硬盘或等效产品)往往具有更高的数量级。

    为了能够使用这么多的位而不会丢失,我们必须将它们分成代表信息片段的块。在JavaScript环境中,这些块称为值。虽然所有值都是由比特组成的,但它们扮演着不同的角色。每个值都有一个确定其角色的类型。有些值是数字,有些值是文本,有些值是函数,依此类推。

    要创建值,你只需调用其名称即可。这很方便。你无需为你的值收集建筑材料或为其付费。你只需要定义一个,然后嗖的一声,你拥有它。当然,它们并非真正从空气中创造出来。每个值都必须存储在某个地方,如果你想同时使用大量的值,则可能会耗尽内存。幸运的是,只有当你同时需要它们时,这才是问题。一旦你不再使用一个值,它就会消散,留下它的位作为下一个值的建筑材料。

    本章介绍JavaScript程序的原子元素,即简单的值类型,和可以对这些值起作用的运算符。

    数字

    该值数类型是勿庸置疑,数值。在JavaScript程序中,它们编写如下:

    13
    

    在程序中使用它,它将导致数字13的位模式在计算机内存中出现。

    JavaScript使用固定数量的位(其中64位)来存储单个数字值。64位可以制作很多模式,这意味着可以表示的不同数字的数量是有限的。使用N个十进制数字,您可以表示10的N次方个数字。类似地,给定64个二进制数字,您可以表示2的64次方个不同的数字,大约是18个quintillion(也就18之后有18个零)。天文数字!

    计算机存储器曾经小得多,人们倾向于使用8或16位的组来表示它们的数字。很容易意外地溢出这么小的数字 - 最终得到一个不符合给定位数的数字。今天,即使是放在口袋里的电脑也有足够的内存,所以你可以自由使用64位块,而且只有在处理真正的天文数字时才需要担心溢出。

    但是,并不是所有小于18 quintillion的数字都适合JavaScript编号。这些位也存储负数,因此一位表示数字的符号。更大的问题是还必须表示非全数字。为此,一些位用于存储小数点的位置。可以存储的实际最大整数更多地在9千万亿(15个零)的范围内 - 这仍然是非常大的。

    小数是用点来表示,例如:

    9.81
    

    对于非常大或非常小的数字,您也可以通过添加e(指数),然后是数字的指数来使用科学记数法。

    2.998e8
    

    代表2.998 × 10的8次方 = 299,800,000。

    整数小于上述9千万亿的计算保证始终精确。不幸的是,使用小数的计算通常不是精确的。例如π(pi)不能用有限数量的十进制数精确表示一样,当只有64位可用于存储它们时,许多数字会失去一些精度。这有些可惜,但它只会在特定情况下引起实际问题。重要的是要注意把小数视为近似值,而不是精确值。

    算术

    与数字有关的主要是算术。加法或乘法等算术运算需要两个数值,并从中产生一个新数字。这是他们在JavaScript中的样子:

    100  +  4  *  11
    

    这里‘+’和‘*’符号称为运算符。第一个代表加法,第二个代表乘法。将运算符放在两个值之间将其应用于这些值并生成新值。

    但是这个例子的意思是“加4和100,并将结果乘以11”,还是在加法之前完成乘法?正如你可能已经猜到的那样,乘法首先发生。但是在数学中,你可以通过在括号中包含加法来改变这一点。

    (100  +  4)*  11
    

    对于减法,有-运算符,可以与/运算符进行除法。

    当运算符一起出现而没有括号时,它们的应用顺序取决于运算符的优先级。该示例显示乘法在加法之前出现。“/”和"*"运算符具有相同的优先级。同样的“+”和“-”也具有相同的优先级。当具有相同优先级的多个运算符彼此相邻时,如在中1 - 2 + 1,它们从左到右运算的:(1 - 2) + 1

    这些优先规则不是你应该担心的。如有不确定,只需添加括号即可。

    还有一个算术运算符,您可能无法立即识别。“%”符号用于表示余数操作。X % Y是表示X除Y的余数。例如,314 % 100的余数是14和144 % 12的余数是0。余数运算符的优先级与乘法和除法的优先级相同。你还经常会将此运算符称为模数。

    特殊号码

    JavaScript中有三个特殊值,它们被视为数字但不像普通数字那样。

    前两个是Infinity-Infinity,代表正负无穷大。Infinity - 1仍然Infinity,等等。但是,不要过分信任基于无穷大的计算。它不是数学上的意义,它将很快导致下一个特殊数字:NaN

    NaN代表“不是数字”,即使它是数字类型的值。例如,当您尝试计算0 / 0(零除以零)Infinity - Infinity,或任何不产生有意义结果的数值运算时你将得到此结果。

    字符串

    下一个基本数据类型是字符串。字符串用于表示文本。它们是通过将其内容括在引号中来编写的。

    `Down on the sea`
    "Lie on the ocean"
    'Float on the ocean'
    

    您可以使用单引号,双引号或反引号来标记字符串,只要字符串的开头和结尾处的引号匹配即可。

    几乎任何东西都可以放在引号之间,JavaScript会从中产生一个字符串值。但是一些角色更难。你可以想象如何在引号之间加上引号可能很难。只有在使用反引号(`)引用字符串时,才能包含换行符(当您按Enter键时获得的字符)而不转义。

    为了能够在字符串中包含这些字符,使用以下表示法:每当在引用文本中找到反斜杠(\)时,它表示后面的字符具有特殊含义。这称为逃避角色。以反斜杠开头的引号不会结束字符串,而是它的一部分。在反斜杠后加上n字符时(\n),它将被解释为换行符。类似地,t反斜杠后面的意思是制表符。请使用以下字符串:

    “这是第一行\ n这是第二行”
    

    包含的实际文本是:

    这是第一行
    这是第二个
    

    当然,在某些情况下,您希望字符串中的反斜杠只是反斜杠,而不是特殊代码。如果两个反斜杠相互跟随,它们将一起折叠,并且只有一个将留在结果字符串值中。

    "A newline character is written like \"\\n\"."
    

    包含的实际文本是:

    A newline character is written like "\n".
    

    字符串也必须被建模为一系列位,以便能够存在于计算机内部。JavaScript执行此操作的方式基于Unicode标准。该标准几乎为你需要的每个角色分配一个数字,包括希腊语,阿拉伯语,日语,亚美尼亚语等字符。如果我们为每个字符都有一个数字,则可以通过一系列数字来描述字符串。

    这就是JavaScript的作用。但是有一个复杂因素:JavaScript的表示法每个字符串元素使用16位,最多可以描述2 16个不同的字符。但是Unicode定义了比这更多的字符 - 大约是此时的两倍。因此,一些字符,例如许多表情符号,在JavaScript字符串中占据两个“字符位置”。我们将在第5章回到这一点。

    字符串不能被分割,相乘或减去,但可以在它们上使用+运算符。它不是代表添加,而是连接: 将两个字符串粘合在一起。以下行将生成字符串:

    “con”  +  “cat”  +  “e”  +  “nate” //"concatenate"
    

    字符串值具有许多可用于对其执行其他操作的关联函数(方法)。我们将在第4章中详细介绍这些内容。

    使用单引号或双引号写的字符串表现非常相似 - 唯一的区别在于您需要在其中转义哪种类型的引号。反引号引用的字符串,通常称为模板文字,可以做更多的技巧。除了能够跨越线条,它们还可以嵌入其他值。

    `100一半是$ { 100  /  2 } `
    

    当您${}在模板文字中写入内容时,其结果将被计算,转换为字符串,并包含在该位置。该示例产生“ 100的一半是50 ”。

    一元运算符

    并非所有运算符都是符号。有些是作为文字写的。一个例子是typeof运算符,它产生一个字符串值,命名你给它的值的类型。

    console.log(typeof 4.5)
    // → number
    console.log(typeof "x")
    // → string
    

    我们将console.log在示例代码中使用来表明我们想要查看评估内容的结果。更多关于下一章的内容。

    显示的其他运算符都在两个值上运行,但typeof只需要一个。使用两个值的运算符称为二元运算符,而使用一个值的运算符称为一元运算符。减运算符既可以用作二元运算符,也可以用作一元运算符。

    console.log(- (10 - 2))
    // → -8
    

    布尔值

    具有区分仅两种可能性的值通常是有用的,例如“是”和“否”或“开”和“关”。为此,JavaScript有一个布尔类型,它只有两个值,true和false,它们被写为这些单词。

    比较

    以下是生成布尔值的一种方法:

    console.log(3 > 2)
    // → true
    console.log(3 < 2)
    // → false
    

    ><标志是传统的符号“大于”和“小于”。他们是二元运算符。应用它们会产生一个布尔值,表示在这种情况下它们是否成立。

    字符串可以以相同的方式进行比较。

    console.log("Aardvark" < "Zoroaster")
    // → true
    

    排序字符串的方式大致是字母顺序,但并不是您希望在字典中看到的内容:大写字母总是“小于”小写字母,因此"Z" < "a",还包括非字母字符(!, - 等等)。比较字符串时,JavaScript会从左到右遍历字符,逐个比较Unicode代码。

    其他类似的运算符是>=(大于或等于),<=(小于或等于),==(等于)和!=(不等于)。

    console.log("Itchy" != "Scratchy")
    // → true
    console.log("Apple" == "Orange")
    // → false
    

    JavaScript中只有一个值与自身不相等,即NaN(“不是数字”)。

    console.log(NaN == NaN)
    // → false
    

    NaN应该表示无意义计算的结果,因此,它不等于任何其他无意义计算的结果。

    逻辑运算符

    还有一些操作可以应用于布尔值本身。JavaScript支持三个逻辑运算符:and, or, not 。这些可以用来“推理”布尔值。

    &&运算符表示逻辑和。它是一个二元运算符,只有当给定的值都为真时,结果才为真。

    console.log(true && false)
    // → false
    console.log(true && true)
    // → true
    

    ||运算符表示逻辑或。如果给定的值中的任何一个为真,则它产生true。

    console.log(false || true)
    // → true
    console.log(false || false)
    // → false
    

    false作为感叹号写的(!)。它是一个一元运算符,可以翻转给它!true产生的价值false,并!false给出true。

    将这些布尔运算符与算术运算符和其他运算符混合时,在需要括号时并不总是很明显。在实践中,你通常可以知道我们到目前为止看到的运算符,||优先级最低,然后是&&比较运算符(>==等等),然后是其余运算符。选择此顺序使得在如下所示的典型表达式中,尽可能少的括号是必要的:

    1  +  1  ==  2  && 10  *  10  >  50
    

    我将讨论的最后一个逻辑运算符不是一元的,不是二元的,而是三元的,运算三个值。它用问号和冒号写成,如下所示:

    console.log(true ? 1 : 2);
    // → 1
    console.log(false ? 1 : 2);
    // → 2
    

    这个被称为条件运算符(或者有时只是三元运算符,因为它是该语言中唯一的这样的运算符)。问号左侧的值“选择”其他两个值中的哪一个将出现。如果为true,则选择中间值,如果为false,则选择右侧的值。

    空值

    有两种特殊值,写入nullundefined,被用来表示不存在的值。它们本身就是值,但它们没有任何信息。

    语言中的许多操作没有产生有意义的价值(稍后会看到一些)之所以用到undefined是因为它们必须产生一些值。

    undefinednull在意义上的差异是JavaScript的设计的意外,大部分时间它们的差异是无关紧要的。如果你不得不关注这些值,我建议将它们视为大多数可互换的。

    自动类型转换
    在简介中,我提到JavaScript几乎不接受任何你给它的程序,甚至是做奇怪事情的程序。以下表达式很好地证明了这一点:

    console.log(8 * null)
    // → 0
    console.log("5" - 1)
    // → 4
    console.log("5" + 1)
    // → 51
    console.log("five" * 2)
    // → NaN
    console.log(false == 0)
    // → true
    

    当运算符应用于“错误”类型的值时,JavaScript将使用一组通常不是你想要或期望的规则时,它会自动地转换它们为所需的类型。这称为类型强制。所述null在第一表达式变为0,并且"5"在第二表达式变为5(从字符串到数字)。然而在第三个表达式中,+在数字加法之前尝试字符串连接,因此1转换为"1"(从数字到字符串)。

    当某些未以明显方式(例如"five"undefined)映射到数字的内容转换为数字时,您将获得该值NaN。关于NaN继续生成的进一步算术运算NaN,所以如果你发现自己在意想不到的地方找到其中一个,那就找出偶然的类型转换。

    当使用相同类型的值进行比较时==,结果很容易预测:当两个值相同时,您应该得到真实,除非是NaN。但是当类型不同时,JavaScript会使用一组复杂而混乱的规则来确定要执行的操作。在大多数情况下,它只是尝试将其中一个值转换为另一个值的类型。然而,当nullundefined在运算符的任一侧时,它仅当双方都是nullundefined时才是true

    console.log(null == undefined);
    // → true
    console.log(null == 0);
    // → false
    

    这种行为通常很有用。如果要测试值是否具有实际值而不是null或undefined,可以将其与null 进行 ==(或!=)的运算符比较。

    但是,如果你想测试一些东西是否指的是精确值false呢?像表达式0 == false"" == false是由于自动类型转换才得到true。当您不希望发生任何类型转换时,还有两个额外的运算符:===!==。第一个测试一个值是否与另一个值完全相等,第二个测试它是否不完全相等。所以"" === false的假设是错误的。

    我建议使用三字符比较运算符进行防御,以防止意外的类型转换绊倒你。但是当你确定双方的类型相同时,使用较短的运算符没有问题。

    逻辑运算符的短路

    逻辑运算符&&||以特殊方式处理不同类型的值。他们会将左侧的值转换为布尔类型以决定做什么,但根据操作符和转换结果,它们将返回原始左侧值或右侧值。

    该||,例如,将值返回至其左侧行驶时可以转换为true,将其返回值正确,否则。当值为布尔值时,这具有预期的效果,并且对其他类型的值执行类似的操作。

    console.log(null || "user")
    // → user
    console.log("Agnes" || "user")
    // → Agnes
    

    我们可以使用此功能来处理默认值。如果你的值可能为空,则可以在||其后面添加替换值。如果初始值可以转换为false,那么你将获得替换。将字符串和数字转换为布尔值的规则表明0NaN和空字符串("")计数为false,而所有其他值都计为true。因此0 || -1得到-1, "" || "!?"得到"!?"

    &&运算符工作方式类似,但是往不同的方向。当左边的值是转换为false的值时,它返回该值,否则返回右边的值。

    这两个运算符的另一个重要特性是仅在必要时评估其右侧的部分。在这种情况下true || X,无论是什么X- 即使它是一个做一些可怕事情的程序- 结果将是真实的,并且X永远不会被评估。这同样适用false && X,它代表永远false,X将被忽略。这称为短路评估。

    条件运算符以类似的方式工作。在第二个和第三个值中,仅评估所选的一个值。

    概要

    我们在本章中查看了四种类型的JavaScript值:数字,字符串,布尔值和未定义的值。

    通过键入其名称(true,null)或值(13,"abc")来创建此类值。您可以将值与运算符组合和转换。我们看到二元运算符的运算(+,-,*,/,和%),字符串连接(+),比较(==,!=,===,!==,<,>,<=,>=),逻辑(&&,||),以及一些一元运算符(-相反数,!否定逻辑上,并typeof找到一个值的类型)和一个三元运算符(?:)根据第三个值选择两个值之一。

    这为你提供了足够的信息,可以将JavaScript用作袖珍计算器。在下一章将开始我们将把这些表达式运用到基础的程序里。

    -- 梵总(j4fun.com)根据谷歌翻译完成于2018年7于21日 (转发请注明出处)