[Just JavaScript] 03. 变量和值 React核心成员Dan Abramov的JavaScript教程中文翻译版

2020-03-25 23:53:53

JavaScript原始值可以改变吗?可以给原始值设置属性吗?变量是值吗?变量和值的联系是什么?让我们连线JavaScript宇宙中的变量和值,重构你对JavaScript变量和值的思维模式。

让我们从一个小代码片段,开始本节内容的学习。

let reaction = 'yikes';
reaction[0] = 'l';
console.log(reaction);

你希望的这段代码做什么?我们还没与报道,所以如果你不确定的话没有关系。试着用你目前的JavaScript知识来回答这个问题

现在,我想让你花点时间,一步一步地写下这段代码每一行的确切思考过程。注意你现在的思维模型中的任何分歧和不确定性,并把它们也写下来。如果你对此有任何疑问,尽量清楚地表达出来。

-------------------------------------------------

                 遮住下面的内容的分隔板

-------------------------------------------------

仰望宇宙星系的女孩


在你写完之前,请不要滚动。


这是答案,此代码将打印出“yikes”或抛出错误,具体取决于你是否处于严格模式*,它永远不会打印“likes”(喜欢)

是的。

严格模式的定义:

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Strict_mode


·原始值是不可变的


你答对了吗?这可能看起来是一个细枝末节的问题,这类问题人们习惯在JavaScript面试中问,而很少在实践中遇到。即使如此,它也说明了关于原始值的而一个重要观点。


我不能改变原始值。


我将用一个小例子来解释这一点。字符串(原始值)和数组(非原始值,它们是对象)有一些表面上的相似之处。数组是项序列,字符串是字符序列:

let arr = [212, 8, 506];
let str = 'hello';

您可以像访问字符串的第一个字符一样,访问数组中的第一项。几乎感觉字符串是数组(但它们不是!):

console.log(arr[0]); // 212
console.log(str[0]); // "h"

你可以更改数组的第一项:

arr[0] = 420;
console.log(arr); // [420, 8, 506]

从直觉出发,很容易假设我们可以对字符串转执行相同的操作:

str[0] = 'j'; // ???


但是你不能。


这里有一点很重要,需要添加到我们的思维模型中。字符串是原始值。这意味着很多!


所有原始值都是不可变的。“不变”是拉丁语中一种奇特的说法“不变”。制度,你不能改变原始值,完全不能。


如果你试图在给原始值设置一个属性,不管是数字、字符串,还是其他什么,JavaScript不会允许您这样做。它是否会自动拒绝您的请求或抛出错误,这取决于您的代码运行在哪种模式。


但是请放心,这允许行不通:

let fifty = 50;
fifty.shades = 'gray'; // No!

JavaScript严格模式和非严格模式下为原始值设置属性的结果  


与任何数字一样,50是一个原始值,不能对其设置属性。


 不能点下面的链接:

https://www.youtube.com/watch?v=otCpCn0l4Wo

在我的JavaScript宇宙之中,所有原始值都存在于距离我的代码更远的轨道上 —— 像遥远的星星。这会提醒我,即使我可以引用它们,我也无法更改它们。它们始终保持原样。


我觉得很奇怪,但是很舒服。

在JavaScript中宇宙,可以修改的变量像行星,不能修改的原始值在更远的行星轨道上


·矛盾吗?


我刚刚演示了原始值是只读的,或者用我们这个时代的话说,是可不可变的。这里有一个片段来测试你的心理模型。


let pet = 'Narwhal';
pet = 'The Kraken';
console.log(pet); // ?


像以前一样,用几句话写下你的思考过程。别急着往前走。一步一步地关注你对每一行的想法。原始值的不可变性在这里起作用吗?它在这里起什么作用?


-------------------------------------------------

                         阻挡板警报

-------------------------------------------------



如果你认为我是在扰乱你的思维,那你完全是对的!答案是“The Kraken”字符串的不可变性子完全不起作用。


如果你回答错误,没有注意它的到来,不要绝望!最后这两个例子看起来肯定是相互矛盾的。


这是一个重要的认识。


当你对一门语言不熟悉时,你可能会倾向于忽略矛盾。毕竟,如果你较真于每一个矛盾,你会钻牛角尖,学不到任何东西。但是既然你致力于建立一个思维模型,你需要质疑矛盾。这样将完美填补思维模型的空白。


·变量是连线

让我们看看这个例子。

let pet = 'Narwhal';
pet = 'The Kraken';
console.log(pet); // "The Kraken"


我们知道字符串值不能修改,因为它们是原始值。但是pet变量的值确实变成了“Kraken”。怎么了?

这似乎是一个矛盾,但是事实并非如此。我们只说原始值不能改变。没说变量也不能改变。

当我们完善思维模型时,我们可能需要理清相关概念。

变量不是值。

变量指向值。


在我的JavaScript宇宙中,变量是一根连线。它有两个端点和一个方向:它从代码中的一个名称开始,指向我的宇宙中的某个值。

例如,我可以将pet变量指向“Narwhal”值。

let pet = 'Narwhal';

变量pet 连线 到 值 Narwhal 的动画演示


在那之后,我们可以对变量做两件事。


· 给变量赋值


我唯一可以做的一件事是给变量赋值:

pet = 'The Kraken';

变量pet 更改连线指向 到 值 The Kraken 的动画演示

我正在做的事只是将JavaScript中的连线左侧(我的Pet变量)指向右侧(“The Kraken”值)。它将一直指向那个值,除非稍后我们重新分配它。

注意,我们不能把其它任何东西放到左边。

'war' = 'peace'; // Nope. (Try it in the console.)

当赋值表达式的左边也是原始值的时候,Chrome浏览器的控制台会报错

赋值的左边必须是一个连线。现在,我们只知道变量是“连线”。但是还有另外一种“连线”。我们将在后面的模块中讨论。也许,你能猜出是什么?(提示:它包括括号或点,我们已经见过很多次了。)

还有另一条规则。

赋值的右侧必须是表达式。它可以是简单的。像2或“hello”,也可以是更复杂的表达式。例如:

pet = count + ' Dalmatians';

这里,count + Dalmatians 是一个表达式,对JavsScript来说是一个问题。JavaScript将用一个值(例如,“101 Dalmatians”)来回答这个问题。从现在起,pet的连线将指向该值。


如果右边必须是一个表达式,这是否意味着像 2 这样的数字或像用户代码编写的“the Kraken”这样的字符串也是表达式?对!这样的表达式也称为文字 —— 因为我们逐字记录它们的值。


· 读取变量的值


我还可以读取变量的值 —— 例如,想要打印它:

console.log(pet);

这并不奇怪。

但是请注意,我们传递给console.log的不是pet变量。通俗地说,我们不能把变量传给函数。我们传的是pet变量的当前值。这究竟是怎么回事?

原来,像pet这样的变量名也可以作为表达式!当我们写pet时,我们在问JavaScript一个问题:“pet的当前值是什么?”为了回答这个问题,JavaScript顺着pet的“连线”,并在“连线”的末尾找到pet的值。

所以同一个表达式在不同的时间会给我们不同的值!


· 名词和动词


谁在乎你说的是“传递变量”还是“传递值”?比较这种差别不是毫无意义吗?我当然不鼓励打断你同事的工作来纠正他们,甚至是你自己。那会浪费大家的时间。

但是在你的思维模型中,你需要清楚地知道你可以用每一个概念的意义。你不会滑冰,你不能让油梨起飞,你不会唱蚊子的歌,你也不能传递一个变量,至少不能用JavaScript传递。

这里有一个小例子说明为什么这些细节很重要。

function double(x) {
  x = x * 2;
}

let money = 10;
double(money);
console.log(money); // ?

如果我们认为double(money)传递了一个变量,那么我们可以期待 x = x * 2 将使变量加倍。但事情不是这样的。我们知道 double(money) 的意思是“找到 moeny 的值,将值传递给 double”。所以答案是 10。真是个骗局!

你脑子里有哪些不同的JavaScript名词和动词?他们之间有什么关系?写下你最常使用的一个小单子。


· 将它们放在一起


现在让我们重温一下来自思维模型的第一个例子:

let x = 10;
let y = x;
x = 0;

我们建议你拿一张纸或打开一个绘图应用程序,一步步地画出x和y变量的连线情况。


  · 第一条线的作用不大:

变量x 连线 到 值 10 的动画演示

· 声明一个名称为 x 的变量

  · 为变量 x 画上一条线

· 给变量 x 赋值10

  · 将变量 x 与 值10 连起来


  · 第二行很短,但是它有很多功能:

变量 y 连线 到  变量 x 的值的动画演示

· 声明一个变量叫做 y

  · 为变量 y 画上一条线

· 为变量 y 赋值 变量 x 的值

  · 计算表达式:x

     · 我们想要回答的“问题”是 x

     · 顺着 x 的连线 —— 找到答案是 10

   · 表达式 x 的结果是 10

   · 因此,为变量 y 赋值 10

      · 将连线从变量 y 指向值 10


  · 最后让我们到第三行

变量x 连线 到 值 0 的动画演示

· 给变量 x 赋值 0

  · 将变量 x 与 值 0 连起来


最后,变量 x 指向值 0,变量 y 指向值 10。注意 y = x 并不意味着 y 点 到 x 点。我们不能把变量指向彼此!变量总是指向值。当我们看到一个赋值时,我们“询问”右边的值,并将左边的“线”指向它。


我在思维模型中提到,把变量看作盒子是相当普遍的。我们要建造的宇宙中,根本没有盒子,它只有连线!这看起来有点烦人。为什么我们不能“将0和10放入变量中,而不是将变量指向它们?”


使用连线对于解释许多其他概念非常重要,比如严格相等、对象标识和变异。我们要坚持使用电线,所以你最好现在就开始习惯!


我的宇宙充满了连线。


· 总结


· 原始值是不可改变的。在我们的代码总,我们无法做任何事情来影响或更改它们。它们将保持原样。例如,不能对字符串值设置属性,因为它是原始值。数组不是原始值,所以我们可以设置它们的属性。

· 变量不是值。每个变量都指向一个特定的值。我们可以使用=赋值运算符更改它指向的值。

· 变量就像连线。“连线”不是JavaScript的概念 —— 但是它帮助我们想像变量是如何指向值的。还有一种不同的“连线”不是变量,但是我们还没有讨论过。

· 注意矛盾。如果你学过的两种事情互相之间有矛盾,不要失望。通常这是一个迹象,表明有一个更深的真相潜伏在下面。

· 名词和动词都很重要。我们正在建议一个思维模型,这样我们就能对宇宙可能发生或不可能发生的事情充满信心。随便说说马虎是可以的,但是我们的思维模型需要精确。


· 练习

本节也有题目供您练习!

点击下面的链接通过少量的小练习来巩固你的思维模型:

https://eggheadio.typeform.com/to/RWJg3m


不要跳过它们哦


即使你已经对变量的概念很熟悉了,这些练习能帮助你巩固我们建立的思维模型。我们需要以此为基础为更更多复杂的话题作准备。


干杯!

Dan


原作者:Dan Abramov

原标题:[Just JavaScript]02. Values and Variables

网站: https://overreacted.io 

翻译:小宇


上一节:

 

 
115210
小宇
ShopXO插件 ▶力扣 ▶Github ▶M站
JustJavaScript
DanAbramov
[Just JavaScript] 02. JavaScript的宇宙 React核心成员Dan Abramov的JavaScript教程中文翻译版
什么是值,JavaScript中哪几种类型,每种类型的用途的是什么?如何通过表达式向JavaScript提问,如何检查值的类型。本节让我们一起探索JavaScript的宇宙。
https://eggheadio.typeform.com/to/PLyTKB
https://www.liquidweb.com/kb/what-is-a-progressive-jpeg
JustJavaScript
DanAbramov
[Just JavaScript] 01. 思维模型 React核心成员Dan Abramov的JavaScript教程中文翻译版
还记得你初学JavaScript时,是如何理解变量的吗?本教程将从心理学入手,教你重新认识JavaScript,培养正确高效的思维模式。来自React核心团队成员和Redux作者Dan Abramov的全新JavaScript教程《Just JavaScript》第一节——思维模型中文翻译版。
https://overreacted.io