JavaScript是由什么制成的?

在使用JavaScript的最初几年中,我感觉很冒昧。 即使我可以使用框架创建网站,但我仍然感觉缺少某些东西。 JavaScript面试使我感到恐惧,因为我对这种语言的基本知识不甚了解。



多年以来,我建立了一个心理JavaScript模型,使我充满信心。 在这里,我将与您分享此模型的非常简洁的版本。 它的结构类似于字典。 每个概念用几句话描述。

阅读本文时,请尝试从心理上评估您对此处讨论的每个问题的信心。 而且,如果事实证明您似乎对这里的很多事情不太熟悉,我也不会因此怪罪您。 但是,如果这是真的,则材料末尾会有一些内容可以帮助您纠正这种情况。

JavaScript心理模型


  • 价值。 含义的概念有点抽象。 这是“东西”。 JavaScript中的值与数学中的数字或几何中的点相同。 当您的程序运行时,该程序的世界充满了意义。 像1420这样的数字是值。 但是意义是其他实体。 例如,句子"Cows go moo" 。 是的,并非一切都有意义。 数字是值,但是if不再是值。 下面我们将讨论不同种类的价值。

    • 值的类型。 值有各种“类型”。 例如,数字(如420 ,字符串(如"Cows go moo" )是对象。 还有其他类型的值。 您可以使用typeof运算符找出值的类型。 例如,命令console.log(typeof 2)会将number输出到控制台。
    • 原始值。 一些值具有“原始”类型。 这些是数字,字符串和其他一些含义。 基本值的一个有趣特性是,您创建的此类值不能超过语言中的值,不能更改现有的基本值。 例如,每次您在代码中使用数字2时,它都将是相同的值2 。 不可能在程序中“再创建”一个值2 ,或将2 “转”为3 。 字符串也是如此。
    • 值为nullundefined 这是两个特殊含义。 它们与其他人不同,原因是它们无法完成很多事情-它们的外观经常会导致错误。 通常,使用null表示没有故意将某个值分配给变量,而undefined表示偶然丢失了一些值。 但是,程序员决定如何准确使用这些值。 这些值之所以存在,是因为有时在执行某个操作的过程中发生错误更好,并且在“处理”不存在的值之后继续执行程序不会发生。
  • 平等 就像意义的概念一样,平等的概念是JavaScript的基本概念之一。 我们要说的是,如果两个值相等的话……实际上,我不会那么说。 如果两个值相等,则意味着它们是一个相同的值。 不是两种不同的含义,而是一种! 例如,等式"Cows go moo" === "Cows go moo"2 === 2真。 一切都清楚了: 22 。 请注意,我们使用三个等号,它们代表上述JavaScript中的值相等概念。

    • 严格平等。 我们只是在上一段中谈到了他。
    • 链接平等。 我们也谈到了他。
    • 不平等。 哦,但这是完全不同的东西。 在JavaScript中,使用包含两个等号( == )的运算符来检查值的非严格相等性。 即使实体由看起来彼此相似(例如2"2" )的不同含义表示,它们也可以大致彼此相等。 为了方便起见,在语言开发的早期阶段,向JavaScript添加了非严格相等运算符。 从那时起,它一直是无底混乱的根源。 松散相等的概念不能被称为基本概念,但它是错误的典型来源。 您可以在下雨天学习非严格相等运算符,但是许多人只是简单地尝试不使用==运算符。
  • 字面量。 当通过将值写入程序代码来引用值时,将使用文字。 例如, 2是数字文字,而"Banana"是字符串文字。
  • 可变的。 变量允许您使用名称引用值。 例如, let message = "Cows go moo" 。 在代码中使用了类似的构造之后,无论何时需要"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" 。 此操作称为将变量分配给值,或将某些内容写入变量,或设置变量。
    • 关键字letconstvar 通常, let是声明变量的最佳关键字。 如果要确保没有新内容可以写入变量,可以使用const关键字。 (在某些代码库和命令中,此问题很棘手,迫使所有人,如果仅将值写入变量一次,请使用const 。)请尽量不要使用var关键字,因为带有声明的变量,相关规则涉及到变量范围的定义。
  • 输入Object Object类型(属于其的实体称为对象)在JavaScript中扮演特殊角色。 对象的显着特征是它们可以与其他值关联。 例如, {flavor: "vanilla"}对象的flavor属性指向"vanilla"的值。 可以将对象视为独立的值,从中可以得出与其他值的链接。

    • 对象的属性。 属性就像来自对象的“连接”一样,它表示某个值。 这可能使您想起了变量的概念:属性具有名称(如flavor ),它指向值(如"vanilla" )。 但是,与变量不同,属性“存在”于对象本身内部,而不是位于代码的某个位置(在变量的特定范围内)。 属性被视为对象的一部分,而属性引用的值不被视为对象的一部分。
    • 对象文字。 对象文字是一种机制,允许您通过在代码中引入适当的构造来创建对象。 例如,这是{}{flavor: "vanilla"} 。 在大括号中,可以声明许多成对的form : (用逗号分隔)。 这使我们可以指定对象属性引用的值。
    • 对象的身份。 我们已经说过2等于2 (换句话说2 === 2 ),因为无论我们在哪里写数字2 ,我们都将“相同”的值称为该位置。 但是每次我们写{} ,我们总是得到不同的值。 结果,形式为{}一个对象不等于另一个看起来也为{} 。 尝试在控制台中编写以下内容: {} === {} (结果将为false )。 当计算机在代码中遇到数字2时,它始终使用相同的演绎方式工作。 但是对象文字是另外一回事。 当计算机遇到{} ,它将创建一个新对象,该对象始终是新值。 如何检查对象是否相等? “平等”的概念可以被视为“价值的同一性”的概念。 当我们说:“ ab相同”时-这意味着我们意味着ab指示相同的值(即a === b )。 当我们说ab不相同时,这意味着ab表示不同的值(即a !== b )。
    • 点符号。 当您需要读取对象的属性值或向属性中写入内容时,可以使用点表示法( . )。 例如,如果变量iceCream指向其属性flavor包含字符串"chocolate" ,则iceCream.flavor构造将为我们提供"chocolate"
    • 括号符号。 有时,事先不知道要访问的对象的属性名称。 例如,有时您需要读取iceCream.flavor属性的值,有时您需要阅读iceCream.flavor属性的值。 括号符号( [] )使您可以通过使用变量设置对象的名称来访问它们的属性。 例如,假设代码中有这样一个变量: let ourProperty = 'flavor' 。 这意味着像iceCream[ourProperty]这样的设计将为我们提供"chocolate"值。 有趣的是,在创建对象时可以使用括号表示法: { [ourProperty]: "vanilla" }
    • 变异。 我们正在谈论的事实是,如果有人向其属性写入新值,则该对象会发生突变(或更改)。 例如,如果我们创建了一个对象let iceCream = {flavor: "vanilla"} ,则稍后我们可以使用iceCream.flavor = "chocolate"为该属性分配一个新值。 请注意,即使我们使用const关键字声明了变量iceCream ,也不会阻止我们更改iceCream.flavor对象的属性。 这是因为使用const仅保护iceCream变量不被覆盖,并且我们更改了该变量引用的对象的flavor属性。 某些人仅因为此关键字会误导程序员而拒绝使用const
    • 数组 数组是一个对象,它是某些值的集合。 例如,可以使用数组文字声明数组,例如: ["banana", "chocolate", "vanilla"] 。 使用这样的构造导致创建一个对象,其名称为0的属性指向字符串"banana" ,属性1指向字符串"chocolate" ,属性2指向值"vanilla" 。 像这样写同样的东西很麻烦: {0: ..., 1: ..., 2: ...} 因此,数组是有用的结构。 数组具有旨在与它们的元素一起使用的内置机制。 其中包括mapfilterreduce方法。 如果名称reduce似乎让您感到困惑,请不要气our。 似乎每个人都无法理解。
    • 原型。 如果您尝试访问不存在的对象会怎样? 例如,如果我们访问iceCream.taste并且该对象仅具有flavor属性,会发生什么? 如果我们不详细回答这个问题,那么可以说,如果我们尝试使用不存在的属性,则会得到undefined的特殊值。 如果您对此问题给出详细的答案,那么您需要从一个事实开始,即JavaScript中的大多数对象都具有所谓的“原型”。 对象的原型可以被视为“隐藏”属性,如果系统不位于对象本身中,则该属性会告诉系统在哪里搜索所请求的属性。 在我们的示例中,当证明iceCream对象iceCream具有iceCream属性时,JavaScript会在也是对象的对象原型中寻找该属性。 如果他在那里找不到,那么在原型的原型中,依此类推。 仅当到达原型链的.taste且未找到.taste属性时,才会.taste undefined值。 您很少需要直接使用此机制,但是了解了原型之后,您可以了解为什么iceCream对象具有从未声明过的toString方法。 此方法取自对象的原型。
  • 功能。 函数是一种特殊含义,仅出于表示一段程序代码的目的而存在。 在程序员不想不断编写相同代码的情况下,函数很方便。 类似于sayHi()的函数的“调用”告诉计算机它需要在函数内部执行代码,然后返回到调用该函数的位置。 JavaScript有许多方法可以声明稍微不同的函数。

    • 函数的参数(或参数)。 使用参数可以将某些数据从调用函数的位置传递给函数。 例如,它可能看起来像这样: sayHi("Amelie") 。 函数中参数的行为类似于变量的行为。 根据确切讨论的内容,即有关函数的声明或其调用,使用“参数”和“参数”一词。 尽管术语上的差异是准确的,但实际上,这些术语可以互换使用。
    • 功能表达。 之前我们将字符串值写入变量。 例如, let message = "I am the walrus" 。 事实证明,函数也可以写入变量: let sayHi = function() { }=符号之后的内容称为函数表达式。 它给了我们特殊的含义(功能),这是一段代码。 如果需要执行此代码,则可以调用相应的函数。
    • 函数声明。 程序员可能会厌倦不断编写诸如let sayHi = function() { } 。 如果是这样,则可以在此处使用简短的形式描述函数: function sayHi() { } 。 这种构造称为函数声明。 不用在表达式的左侧指定变量名,而是将这个名称放在function关键字之后。 通常,用于创建上述功能的两种样式可以互换。
    • 将功能提升到示波器的顶部。 通常,只有在使用letconst声明其下方之后,才能使用该变量。 就功能而言,这可能不方便。 函数可以相互调用。 找出最先创建哪个是一项艰巨的任务。 好消息是,在使用函数声明时(并且仅在使用这种方法时!),描述函数的顺序并不重要。 事实是,使用这种方法,功能会“上升”到范围的上部。 也就是说,事实证明,即使您尝试从声明它们之前的代码中调用这些函数,这些函数也已经定义并且可以使用。
    • 这个关键词。 也许关键字this是最常被误解的JavaScript概念。 可以将此关键字与特殊函数参数进行比较。 但是我们自己不会转移其功能。 JavaScript将其传递。 此值取决于函数的调用方式。 例如,当使用点符号(例如iceCream.eat()调用对象方法时, this将指示该点之前的内容。 在我们的示例中,这是一个iceCream对象。 函数中this的值取决于函数的调用方式,而不取决于函数的声明位置。 有一些特殊的方法,例如.bind.apply.apply ,它们使程序员能够控制进入this的能力。
    • 箭头功能。 箭头函数类似于函数表达式。 它们这样声明: let sayHi = () => { } 。 它们结构紧凑,通常用于单线设计。 箭头功能的功能比常规功能的功能受到更多限制。 例如,他们没有关键字this 。 在箭头函数中使用this关键字时,它取自嵌入了箭头函数的函数。 这类似于从嵌套在另一个函数中的函数调用参数或变量。 实际上,这意味着当箭头函数希望它们周围的代码中存在与this函数相同的this值时,可以使用它们。
    • this值绑定到函数。 通常,将某个函数f绑定this函数的特定值以及特定的参数集意味着创建了一个新函数,该函数使用这些预定义值调用函数f 。 JavaScript具有绑定函数的辅助机制.bind方法,但是您可以通过其他方式将其绑定到函数。 绑定是使嵌套函数“看到” this值与它们外部函数相同的一种流行方法。 现在,箭头函数在类似的情况下使用,结果,我们时代很少使用函数绑定。
    • 调用堆栈 调用功能就像进入房间一样。 每次我们调用一个函数时,其中的变量都会再次初始化。 结果,每个函数调用就像使用功能代码建立一个新的“房间”。 当“房间”被“建造”时,被“输入”到其中,执行功能代码。 在此“房间”中的“实时”函数中声明的变量。 当执行功能返回时,“房间”及其所有内容都消失了。 通过函数调用创建的所有这些“房间”都可以表示为高“塔”。 这是一个调用堆栈。 当我们退出某个函数时,我们会到达该函数,该函数位于调用堆栈的“下方”。
    • 递归。 递归是函数调用自身的时候。 在需要重复执行函数已完成的操作但使用其他参数的情况下,此技术很有用。 例如,如果我们编写了一个搜索网站的搜索引擎,则可能具有collectLinks(url)函数。 此函数首先收集位于站点页面上的链接,然后调用自身,将找到的每个链接传递给自身。 , . , , , . , , stack overflow . - , .
    • . — , , . , , — . — , — , , . , .
    • . () — , JavaScript. , , . : . . , setTimeout , … -. , . — . « », , .
    • . , , , , . - , . ? - . — . . , - . JavaScript, , . «». JavaScript, , , , .


JavaScript , . . JavaScript. , . JavaScript. — Just JavaScript . , , JavaScript.

! JavaScript?

Source: https://habr.com/ru/post/zh-CN482472/


All Articles