作者:Dan Abramov 原文链接:What Is JavaScript Made Of? 译者:Yodonicc 译者注:Dan Abramov是Redux的作者、也是React核心开发成员,在React社区中享有很高的声望。本文中,他讲述了自己脑中的JS知识图谱。
在我使用JavaScript的头几年里,我觉得自己是个骗子。尽管我可以用框架建立网站,但还是缺少一些东西。我惧怕JavaScript的工作面试,因为我对基础知识掌握得不够牢固。
多年来,我形成了一个关于JavaScript的心智模型,给了我信心。在这里,我分享的是它的一个非常压缩的版本。它的结构像一个词汇表,每个主题都有几句话。
当你读完这篇文章时,试着在心理上记下你对每个主题的自信程度。如果其中有不少是没有信心的,我也不会对你进行评判。在这篇文章的末尾,有一些东西可能对这种情况有帮助。
420
这样的数字,像 "牛哞哞叫 "
这样的字符串,对象,以及其他一些类型。你可以通过在某个值前面加上typeof来了解它的类型。例如,console.log(typeof 2)
打印出 "number"
。null
和undefined
。这是两个特殊的值。它们之所以特殊,是因为有很多事情你不能用它们来做--它们经常导致错误。通常情况下,null
表示某些值是故意丢失的,undefined
表示某个值是无意丢失的。然而,什么时候使用这两种情况是由程序员决定的。它们的存在是因为有时操作失败比带着一个缺失的值进行操作要好。"Cows go moo" === "Cows go moo"
,2 === 2
,因为2就是2。 注意,我们用三个等号来表示JavaScript中的这个相等概念。
==
)。事物可以被认为是松散相等的,即使它们指的是看起来相似的不同值(比如2
和"2"
)。为了方便起见,它很早就被添加到了JavaScript中,并且从那时起就造成了无尽的混乱。这个概念并不基本,但却是一个常见的错误来源。你可以学习它的工作原理未雨绸缪,但很多人都尽量避免它。let message = "Cows go moo"
。现在你可以写message
,而不是在你的代码中每次都重复同样的句子。你以后可以改变message
来指向另一个值,比如message = "I am the walrus"
。注意这并不改变值本身,而只是改变消息指向的地方,就像一条"线"。它指向的是"Cows go moo"
,而现在它指向的是"I am the walrus"
。
message
变量,那就糟糕了。相反,当你定义一个变量时,它在你的程序的某个部分是可用的。这一部分被称为 "作用域"。作用域是有规则的,但通常你可以在你定义变量的地方寻找最接近的{和}括号。那个代码 "块 "就是它的作用域。message = "I am the walrus "
时,我们改变message
变量,使其指向"I am the walrus "
的值。这就是所谓的赋值、写、或设置变量。let
vs const
vs var
: 通常情况下,你需要let
。如果你想禁止对这个变量进行赋值,你可以使用 const
。(有些代码库和同事很迂腐,强迫你在只有一个赋值时使用 const
) 。尽量避免使用var
,因为它的范围规则很混乱。{flavor: "vanilla"}
对象有一个指向 "vanilla "
值的flavor
属性。把对象看作是 "你自己的 "值,并给外界提供了一条“线”。
flavor
)并指向一个值(像 "vanilla "
)。但与变量不同,属性 "生活 "在对象本身,而不是在你的代码中的某个地方(范围)。一个属性被认为是对象的一部分--但它所指向的值却不是。{}
或{flavor: "vanilla"}
。在{}
里面,我们可以有多个property: value
键值对,用逗号分隔。这让我们可以设置属性的 "线 "从我们的对象指向哪里。2===2
),因为每当我们写2的时候,我们 "召唤 "的是同一个值。但是每当我们写{}
时,我们总是会得到一个不同的值! 所以{}
不等于另一个{}
。在控制台中试试这个。{}==={}
(结果为false)。当计算机在我们的代码中遇到2时,它总是给我们相同的2值。然而,对象字面量是不同的:当计算机遇到{}
时,它会创建一个新的对象,这总是一个新的值。那么,什么是对象ID呢?它是相等的另一个术语,或者说是值的同一性。当我们说 "a和b有相同的ID "时,我们的意思是 "a和b指向相同的值"(a === b
)。当我们说 "a和b有不同的ID "时,我们的意思是 "a和b指向不同的值"(a !==b
)。.
)符号。例如,如果一个变量iceCream
指向一个对象,该对象的属性flavor
指向 "巧克力"
,那么写出iceCream.flavor
就可以得到"巧克力"
。iceCream.flavor
,有时你想读取iceCream.taste
。当属性的名称本身是一个变量时,括号([]
)符号可以让你读取该属性。例如,let ourProperty = 'flavor'
。那么iceCream[ourProperty]
将给我们"巧克力"
。奇怪的是,我们在创建对象时也可以使用它:{ [ourProperty]: "vanilla" }
。let iceCream = {flavor: "vanilla"}
,我们以后可以用iceCream.flavor = "chocolate "
来突变它。注意,即使我们用const
来声明iceCream
,我们仍然可以突变iceCream.flavor
。这是因为const只会阻止对iceCream变量本身的赋值,但我们却突变了它所指向的对象的一个属性(flavor)。有些人发誓不再使用const,因为他们认为这太容易引起误解了。["香蕉"、"巧克力"、"香草"]
这样的数组字面时,你基本上创建了一个对象,其属性0指向 "香蕉 "字符串值,属性1指向 "巧克力 "值,而属性2指向 "香草 "值。写{0: ..., 1: ..., 2: ...}
会很烦人,这就是为什么数组很有用。还有一些对数组进行操作的内置方法,如map
、filter
和reduce
。如果reduce
看起来很混乱,不要绝望——它对每个人来说都是混乱的。iceCream.taste
(但我们的属性叫 flavor
)。简单的答案是我们会得到特殊的未定义值。更细微的答案是,JavaScript中的大多数对象都有一个 "原型"。你可以把原型想象成每个对象上的一个 "隐藏 "属性,它决定了 "下一步要看哪里"。因此,如果冰激凌上没有味道属性,JavaScript会在它的原型上寻找味道属性,然后在该对象的原型上寻找,以此类推,如果它到达这个 "原型链 "的末端而没有找到.taste
,才会给我们未定义。你很少会与这种机制直接互动,但它解释了为什么我们的冰激凌对象有一个我们从未定义过的toString方法——它来自原型。sayHi()
这样的函数,告诉计算机运行里面的代码,然后再回到程序中的位置。在JavaScript中,有很多方法来定义一个函数,它们的作用略有不同。
sayHi("Amelie")
。在函数内部,它们的作用类似于变量。它们要么被称为 "arguments",要么被称为 "parameters",这取决于你阅读的是哪一方(函数定义或函数调用)。然而,这种术语上的区别是迂腐的,在实践中这两个术语是可以互换使用的。let sayHi = function() { }
的东西会很累,所以我们可以用一个更简短的形式来代替:function sayHi() { }
。这就是所谓的函数声明。我们不用在左边指定变量名,而是把它放在函数关键字后面。这两种风格大多是可以互换的。let
或const
声明后使用一个变量。这对于函数来说可能很烦人,因为它们可能需要互相调用,而且很难跟踪哪个函数被其他函数使用,需要先定义。为了方便起见,当(也只有当!)你使用函数声明语法时,它们的定义顺序并不重要,因为它们被 "提升"。这是一种花哨的说法,从概念上讲,它们都被自动移到了作用域的顶部。当你调用它们时,它们都已经被定义了。let sayHi = () => { }
。它们很简明,经常用于单行代码。箭头函数比普通函数更有局限性——例如,它们没有任何 "this "的概念。当你在一个箭头函数里面写这个时,它使用上面最接近的 "常规 "函数的this。这类似于如果你使用一个只存在于上面一个函数中的参数或变量会发生什么。实际上,这意味着人们在使用箭头函数时,希望在其内部 "看到 "与周围代码中相同的this。collectLinks(url)
函数可能首先收集一个页面的链接,然后为每个链接调用自己,直到访问所有的页面。递归的隐患在于,很容易写出永远无法完成的代码,因为一个函数永远在调用自己。如果发生这种情况,JavaScript会用一个叫做 "堆栈溢出 "的错误来阻止它。之所以这样叫,是因为它意味着我们的调用栈中堆积了太多的函数调用,而且它实际上已经溢出了。JavaScript就是由这些概念组成的,而且还有更多。在我能够建立一个正确的心智模型之前,我对自己的JavaScript知识感到非常焦虑,我希望能够帮助下一代的开发者更早地弥补这个差距。
如果你想和我一起深入研究这些主题,我有东西给你。Just JavaScript是我提炼出来的关于JavaScript如何工作的心智模型,它将以惊人的Maggie Appleton的视觉插图为特色。与这篇文章不同的是,它以较慢的速度进行,所以你可以跟随每个细节。
Just JavaScript还处于非常早期的阶段,所以它只能以一系列电子邮件的形式提供,没有经过润色或编辑。如果这个项目听起来很有趣,你可以注册,通过电子邮件接收免费的草稿。我将感谢你的反馈。谢谢你!"。
注:特别感谢技术指导dazhao(赵达)对本文翻译的审阅指正。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。