现在要开始介绍的是值(value)
什么是值?这很难解释。
这就好比是在数学里问是么是数字,在几何学里问什么是点。在JavaScript宇宙中,值是一个事物
数字(numbers
)是值,并且其他的事物也是值,比如 objects
和 functions
。然而,还有一些事物不是值,比如说 if
语句或者变量声明。
代码和值
为了在 JavaScript
程序中区分值和其他事物,我偏向于将它们想象为《小王子》中的一张图:
我站在一个小行星上,这就是我程序里的代码。
在它的表面,我看见了 if
语句、变量声明、逗号、大括号和其他在 JavaScript
中能找到的事物。
我的代码包含了诸如“调用函数”、“一件事情做多少次”,甚至是“抛出错误”等指示。我一步一步地完成这些指示 — 在我的小行星上奔跑。
但是没过一会儿,我都会抬头看(注:这里应该指的是时间循环)
在一个清净的夜晚,我在 JavaScript
天空中看见了不一样的值:booleans
、numbers
、strings
、symbols
、functions
和 objects
,null
和 undefined
— 我的天!虽然我的代码里不存在这些,但是我可能引用过它们。
在我的 JavaScript
宇宙中,值漂浮在空间中。
“等一下”,你也许会说,“我的代码里经常出现这些值”。现在,我希望你在理解上能有质的飞跃。这个心智模型可能需要花费更多的精力才能获得回报。Give it five minutes
回到值上,笼统的来说,值一般有两种。
原始值
原始值(primite values)包括 numbers
、strings
和其他事物。打开你浏览器通过 console.log()
命令打印以下原始值:
console.log(2);
console.log("hello");
console.log(undefined);
所有的原始值都有一些共性。在我的代码里,我无法改变它们。这听起来比较模糊,所以我们将在下个模块里正确的理解这句话。现在,我想说的是这些值就像是星星 — 冰冷且遥远,但是当我需要的时候,它们总是在那儿。
这就是第一种值
对象和函数
Objects and Functions 也是值,但它们不是原始值。这使得它们比较特殊。继续在浏览器中进行下列的输出:
console.log({});
console.log([]);
console.log(x => x * 2);
注意浏览器的控制台在显式它们时和原始值有什么不同。有的浏览器会在它们前面显示一个箭头,或者在点击它们时做一些特别的事情。如果你安装了不同的浏览器(比如说谷歌、火狐),比较它们是如何表现 objects
和 functions
的。
对象和函数之所以特殊是因为我们能通过代码操纵它们。比如,我能通过其他值连接它们。这还是比较模糊 — 所以我们会后面的模块中提炼这个想法。现在,我能说如果原始值像是遥远的星星,那么对象和函数更像是漂浮在我代码旁边的岩石。它们离我太近了以至于我可以操纵它们。
这就是第二种值。
你也许会有一些问题。那好,只要你问,JavaScript
宇宙就会回答你的问题。当然,前提是你知道如何提问。
表达式
这里有很多 JavaScript
无法回答的问题。如果你想问该不该像好朋友表白,那么直到你变为了白骨,JavaScript
都不会给你有用的帮助。
但是也有很多 JavaScript
乐意回到的问题。这些问题有一个共同的名字 — 表达式(expressions)
如果我们问表达式 2 + 2
,那么 JavaScript
会回答 4
。
console.log(2 + 2); // 4
表达式是 JavaScript
能回答的问题。JavaScript
通过它们唯一知道的方式回答 — 值。
如果“表达式”这个词对你有所混淆,可以将其想象为表达一个值的一段代码。你也许听别人说过 2 + 2
的“结果”或者“被计算为” 4
。这只是同一件事的不同说法而已。
我们向 JavaScript
询问 2 + 2
,它回答 4
。表达式总是以一个值作为结果。现在我们对表达式的危险足够了解了(注:没看出危险是啥呢)。
我之前说 JavaScript
中有很多不同类型的值:numbers
、stirngs
、objects
以及其他的。那么我们该怎么知道一个特定值的类型呢。
这听起来像是一个问题,你敢这么问吗?
类型检查
首先,在 JavaScript
宇宙中所有的值都是看起来一样的—天空中明亮的星星。但是你仔细看的话会发现有10种不同的类型。同类型的值有相同的行为。
如果我们想要知道一个值得类型,可以通过 typeof
操作符询问。JavaScript
会用预设的字符来回答我们的问题,比如 number
、string
或者 object
。
你可以在浏览器的控制面板中尝试下列代码。
console.log(typeof(2)); // number
console.log(typeof("hello")); // string
console.log(typeof(undefined)); // undefined
在这里,typeof(2)
是一个表达式 — 然后以 number
作为返回值。
严格地说,typeof
可以不使用括号。例如,typeof 2
和 typeof(2)
作用是一样的。但是,有时候为了避免歧义括号是必须的。下列代码有一句在没有括号的情况下会问题,猜测一下是那一句?
console.log(typeof([])); // object
console.log(typeof({})); // object
console.log(typeof(x => x * 2)); // function
你可以在浏览器的控制面板验证你的猜想。
现在看一下最后的三个例子,仔细观察下它们的结果。你有什么惊讶的发现吗?为什么?
值的类型
作为一个有抱负的天文学家,你也许知道在 JavaScript
宇宙中能监测到的值得所有的类型。接近25年的 JavaScript
研究,科学家们只发现了9中这样的类型
- 原始值
- Undefined(
undefined
)。用于表示无意中未赋值的情况。 - Null(
null
)。用于表示故意未赋值的情况。 - Booleans(
true
和false
)。用于逻辑判断。 - String(
"hello"
、"banana"
和其他)。用于文本。 - Number(1,2,-1和其他)。用于数字。
- Symbols(不常用)。用于隐藏具体的实现。
- Bigints(不通用且新)。用于数学中的大数字的计算。
- Undefined(
- 对象和函数
- Objects(
{}
和其他)。用于组合相关数据和代码。 - Functions(
x => x * 2
和其他)。用于组件代码逻辑。
- Objects(
没有其他类型
你也许会问,“我好向还用过其他类型,比如数组”。
在 JavaScript
中,除了上文中列举的类型外没有其他的基本类型。剩下的都是对象。比如,在 JavaScript
中数组、日期和正则表达式都是对象。
console.log(typeof([])); // "object"
console.log(typeof(new Date())); // "object"
console.log(typeof(/(hello|goodbye)/)); // "object"
你也许会回应到,“一切皆对象!”。可惜这是一个流传很广的都市传说,不是真的。虽然 "hi".toUpperCase()
使得 "hi"
表现得像是一个对象,但这是一个错觉。JavaScript
会在你做这种事儿的时候创建一个基本包装类型,使用之后会立即释放掉。
虽然这个机制解释得不是很清楚,但是你需要记得的是,原始类型(数值、字符串等)不是对象。
回顾
让我们回顾一下这章的内容:
- 在
JavaScript
中有值这个概念。我们可以详细值是漂浮在JavaScript
宇宙中的不同的东西。它们不会直接存在于我们的代码中,但是我们可以在代码中引用它们。 - 有两种分类的值,原始值、对象和函数。一共有9种类型,每个类型都有着各自的目的和行为,不过有的类型很少用到。
- 部分类型只有一个值。例如,
null
是Null
类型唯一的值,并且undefined
是Undefined
类型唯一的值。之后我们会知道,这两个值会是一个麻烦制造者。 - 我们可以向表达式询问问题。
JavaScript
会回答我们答案。例如, 询问2 + 2
,回答4
。 - 我们可以通过
typeof
表达式查询类型。例如,typeof(4)
会返回"number"
。