Appearance
Values and Variables
先看一个小代码片段
let reaction = 'yikes';
reaction[0] = 'l';
console.log(reaction);
你认为这段代码最后的结果是什么呢?我希望你花一点时间,一步一步地写下你对每一行代码的确切思考过程。注意你现有思维模式中的任何空白或不确定因素,也把它们写下来。如果你有任何疑问,尽量清楚地表达出来
带着疑问🤔️我们往下看吧!
Primitive Values Are Immutable(原始值是不可变的)
上面的那道题,你知道正确答案了么,你答对了吗?这似乎是一种只有在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!
像任何数字一样,50是一个原始值。我们不能在上面设置属性。 记住,在我们的JavaScript世界中,所有的原始值都是遥远的星星,离我们的代码最远。我们可以指出它们,但它们将永远停留在原地,不变。 奇怪的是,我觉得这很安慰~
Variables and Values—A Contradiction?(变量和值 矛盾么)
看看下面代码你觉得答案是什么
let pet = 'Narwhal';
pet = 'The Kraken';
console.log(pet); // ?
如果你认为我想弄乱你的脑袋,那你是对的!答案是
"The Kraken"
。不变性在这里不起作用。如果你弄错了,不要绝望!这个例子似乎与字符串不变性相矛盾,但事实并非如此。
当你刚接触一门语言时,有时有必要抛开矛盾,这样你就可以避免兔子洞并继续学习。但既然你致力于建立一个心智模型,你就需要质疑矛盾。
矛盾揭示了心智模型的差距。
Variables Are Wires(变量是连线)
让我们来看看解释
let pet = 'Narwhal';
pet = 'The Kraken';
console.log(pet); "The Kraken"
我们知道字符串值不能改变,因为它们是原始的。但宠物变量确实变成了“海怪”。这是怎么回事? 这似乎是一个矛盾,但它不是。
我们说过原始值不能改变,但是我们没有说任何关于变量的东西!随着我们不断完善我们的思维模式.
我们需要理清几个相关的概念:
- 变量不是值
- 变量指向值
Assigning a Value to a Variable ()
在我们的JavaScript世界中,变量是指向值的连线。 例如,我可以将pet变量指向“Narwhal”值。(我也可以说我把值“Narwhal”赋值给变量pet)
let pet = 'Narwhal';
pet = 'The Kraken';
console.log(pet); // "The Kraken"
pet = 'The Kraken';
- 我在这里所做的一切只是指示JavaScript将左侧(宠物)的变量或“连线”指向右侧(‘the Kraken’)的值。
- 它会一直指向那个值,除非我以后再重新赋值。
Rules of Assignment
- 赋值的左侧必须是“连线”——例如pet变量。
- 赋值的右边必须是一个表达式,所以它总是会产生一个值。我们的表达可以很简单,比如2或者“hello”。它也可以是一个更复杂的表达式——例如 pet = count +'sudongyuer'
在这里,count + ' sudongyuer'是一个表达式——一个JavaScript的问题。JavaScript将用一个值回答它(例如,“101 sudongyuer”)。从现在开始,宠物变量“wire”将指向那个特定的值
如果右边必须是一个表达式,这是否意味着简单的东西,如数字2或字符串,如' the Kraken',写在代码也是表达式?是的!这样的表达式被称为字面量——因为我们字面地写下它们产生的值。
Reading a Value of a Variable
我们当然可以从变量中读取值
console.log(pet);
这是不足为奇的。 但是请注意,它不是我们传递给console.log的pet变量。
我们可以口头上这么说,但是我们不能把变量传递给函数。传递pet变量的当前值。
这是如何工作的? 事实证明,像pet这样的变量名也可以用作表达式!当我们编写pet时,我们要问JavaScript一个问题:“pet的当前值是多少?”为了回答我们的问题,JavaScript跟随宠物“wire”,并返回这个“wire”末尾的值。
所以同一个表达式可以在不同的时间给我们不同的值!
Nitpicking
JS中只有值传递!!!JS中只有值传递!!!JS中只有值传递!!!
谁在乎你说的是“传递一个变量”还是“传递一个值”?这两者之间的区别是不是太迂腐了?我当然不鼓励打断你的同事纠正他们。那是在浪费大家的时间。 但是您需要在头脑中清楚地了解每个JavaScript概念可以做什么。你不能骑自行车溜冰。你不能给蚊子唱歌。而且不能传递变量——至少在JavaScript中不能。 下面是一个小例子,说明为什么这些细节很重要。
function double(x) {
x = x * 2;
}
let money = 10;
double(money);
console.log(money); // ?
回顾
- 原始值是不可变的它们是我们 JavaScript 世界的永久组成部分——我们无法创建、销毁或更改它们。例如,我们不能在字符串值上设置属性,因为它是原始值。数组不是原始的,所以我们可以设置它们的属性。
- 变量不是值每个变量都指向一个特定的值。我们可以使用赋值运算符来更改它指向的值。
=
- 变量就像电线“线”不是 JavaScript 的概念——但它可以帮助我们想象变量如何指向值。当我们进行赋值时,左边总是有一个连线,右边是一个表达式(产生一个值)。
- 注意矛盾如果你学到的两件事似乎相互矛盾,不要气馁。通常这是一个迹象,表明潜藏着更深层次的真相。
- 语言很重要我们正在建立一个心智模型,以便我们对宇宙中可能发生或不可能发生的事情充满信心,我们可能会以随意的方式谈论这些想法(吹毛求疵通常会适得其反),但我们对术语背后含义的理解需要准确。