现在要开始介绍的是值(value)

什么是值?这很难解释。

这就好比是在数学里问是么是数字,在几何学里问什么是点。在JavaScript宇宙中,值是一个事物

数字(numbers)是值,并且其他的事物也是值,比如 objectsfunctions。然而,还有一些事物不是值,比如说 if 语句或者变量声明。

代码和值

为了在 JavaScript 程序中区分值和其他事物,我偏向于将它们想象为《小王子》中的一张图:
little_prince.jpeg
我站在一个小行星上,这就是我程序里的代码。

在它的表面,我看见了 if 语句、变量声明、逗号、大括号和其他在 JavaScript 中能找到的事物。

我的代码包含了诸如“调用函数”、“一件事情做多少次”,甚至是“抛出错误”等指示。我一步一步地完成这些指示 — 在我的小行星上奔跑。

但是没过一会儿,我都会抬头看(注:这里应该指的是时间循环)

在一个清净的夜晚,我在 JavaScript 天空中看见了不一样的值:booleansnumbersstringssymbolsfunctionsobjectsnullundefined — 我的天!虽然我的代码里不存在这些,但是我可能引用过它们。

在我的 JavaScript 宇宙中,值漂浮在空间中。

universe.png
“等一下”,你也许会说,“我的代码里经常出现这些值”。现在,我希望你在理解上能有质的飞跃。这个心智模型可能需要花费更多的精力才能获得回报。Give it five minutes

回到值上,笼统的来说,值一般有两种。

原始值

原始值(primite values)包括 numbersstrings 和其他事物。打开你浏览器通过 console.log() 命令打印以下原始值:

  1. console.log(2);
  2. console.log("hello");
  3. console.log(undefined);

所有的原始值都有一些共性。在我的代码里,我无法改变它们。这听起来比较模糊,所以我们将在下个模块里正确的理解这句话。现在,我想说的是这些值就像是星星 — 冰冷且遥远,但是当我需要的时候,它们总是在那儿。

这就是第一种值

对象和函数

Objects and Functions 也是值,但它们不是原始值。这使得它们比较特殊。继续在浏览器中进行下列的输出:

  1. console.log({});
  2. console.log([]);
  3. console.log(x => x * 2);

注意浏览器的控制台在显式它们时和原始值有什么不同。有的浏览器会在它们前面显示一个箭头,或者在点击它们时做一些特别的事情。如果你安装了不同的浏览器(比如说谷歌、火狐),比较它们是如何表现 objectsfunctions 的。

对象和函数之所以特殊是因为我们能通过代码操纵它们。比如,我能通过其他值连接它们。这还是比较模糊 — 所以我们会后面的模块中提炼这个想法。现在,我能说如果原始值像是遥远的星星,那么对象和函数更像是漂浮在我代码旁边的岩石。它们离我太近了以至于我可以操纵它们。

这就是第二种值。

你也许会有一些问题。那好,只要你问,JavaScript 宇宙就会回答你的问题。当然,前提是你知道如何提问。

表达式

这里有很多 JavaScript 无法回答的问题。如果你想问该不该像好朋友表白,那么直到你变为了白骨,JavaScript 都不会给你有用的帮助。

但是也有很多 JavaScript 乐意回到的问题。这些问题有一个共同的名字 — 表达式(expressions)

如果我们问表达式 2 + 2,那么 JavaScript 会回答 4

  1. console.log(2 + 2); // 4

表达式是 JavaScript 能回答的问题。JavaScript 通过它们唯一知道的方式回答 — 值。

expression.gif

如果“表达式”这个词对你有所混淆,可以将其想象为表达一个值的一段代码。你也许听别人说过 2 + 2 的“结果”或者“被计算为” 4。这只是同一件事的不同说法而已。

我们向 JavaScript 询问 2 + 2,它回答 4表达式总是以一个值作为结果。现在我们对表达式的危险足够了解了(注:没看出危险是啥呢)。

我之前说 JavaScript 中有很多不同类型的值:numbersstirngsobjects 以及其他的。那么我们该怎么知道一个特定值的类型呢。

这听起来像是一个问题,你敢这么问吗?

类型检查

首先,在 JavaScript 宇宙中所有的值都是看起来一样的—天空中明亮的星星。但是你仔细看的话会发现有10种不同的类型。同类型的值有相同的行为。

如果我们想要知道一个值得类型,可以通过 typeof 操作符询问。JavaScript 会用预设的字符来回答我们的问题,比如 numberstring 或者 object
telescope.png
你可以在浏览器的控制面板中尝试下列代码。

  1. console.log(typeof(2)); // number
  2. console.log(typeof("hello")); // string
  3. console.log(typeof(undefined)); // undefined

在这里,typeof(2) 是一个表达式 — 然后以 number 作为返回值。

严格地说,typeof 可以不使用括号。例如,typeof 2typeof(2) 作用是一样的。但是,有时候为了避免歧义括号是必须的。下列代码有一句在没有括号的情况下会问题,猜测一下是那一句?

  1. console.log(typeof([])); // object
  2. console.log(typeof({})); // object
  3. console.log(typeof(x => x * 2)); // function

你可以在浏览器的控制面板验证你的猜想。
typeof.gif
现在看一下最后的三个例子,仔细观察下它们的结果。你有什么惊讶的发现吗?为什么?

值的类型

作为一个有抱负的天文学家,你也许知道在 JavaScript 宇宙中能监测到的值得所有的类型。接近25年的 JavaScript 研究,科学家们只发现了9中这样的类型

  • 原始值
    • Undefined( undefined )。用于表示无意中未赋值的情况。
    • Nullnull )。用于表示故意未赋值的情况。
    • Booleanstruefalse)。用于逻辑判断。
    • String"hello""banana" 和其他)。用于文本。
    • Number(1,2,-1和其他)。用于数字。
    • Symbols(不常用)。用于隐藏具体的实现。
    • Bigints(不通用且新)。用于数学中的大数字的计算。
  • 对象和函数
    • Objects{} 和其他)。用于组合相关数据和代码。
    • Functionsx => x * 2 和其他)。用于组件代码逻辑。

没有其他类型

你也许会问,“我好向还用过其他类型,比如数组”。

JavaScript 中,除了上文中列举的类型外没有其他的基本类型。剩下的都是对象。比如,在 JavaScript中数组、日期和正则表达式都是对象。

  1. console.log(typeof([])); // "object"
  2. console.log(typeof(new Date())); // "object"
  3. console.log(typeof(/(hello|goodbye)/)); // "object"

你也许会回应到,“一切皆对象!”。可惜这是一个流传很广的都市传说,不是真的。虽然 "hi".toUpperCase() 使得 "hi" 表现得像是一个对象,但这是一个错觉。JavaScript 会在你做这种事儿的时候创建一个基本包装类型,使用之后会立即释放掉。

虽然这个机制解释得不是很清楚,但是你需要记得的是,原始类型(数值、字符串等)不是对象。

回顾

让我们回顾一下这章的内容:

  1. JavaScript 中有值这个概念。我们可以详细值是漂浮JavaScript 宇宙中的不同的东西。它们不会直接存在于我们的代码中,但是我们可以在代码中引用它们。
  2. 有两种分类的值,原始值、对象和函数。一共有9种类型,每个类型都有着各自的目的和行为,不过有的类型很少用到。
  3. 部分类型只有一个值。例如,nullNull 类型唯一的值,并且 undefinedUndefined 类型唯一的值。之后我们会知道,这两个值会是一个麻烦制造者。
  4. 我们可以向表达式询问问题。JavaScript 会回答我们答案。例如, 询问 2 + 2,回答 4
  5. 我们可以通过 typeof 表达式查询类型。例如,typeof(4) 会返回 "number"