"Code tailor",为前端开发者提供技术相干资讯以及系列根底文章,微信关注“小和山的菜鸟们”公众号,及时获取最新文章。

前言

在开始学习之前,咱们想要告诉您的是,本文章是对JavaScript语言常识中 "语言根底-语法和变量" 局部的总结,如果您已把握上面常识事项,则可跳过此环节间接进入题目练习

  • JavaScript 语法
  • 申明变量与赋值

汇总总结

第一段代码

在开始学习 JavaScript 时,咱们先看一段 JavaScript 代码,如下:

console.log('Hello JavaScript!')

你能猜到这段代码的后果吗?这段代码的操作就是在控制台输入后果是 Hello JavaScript!,到这里第一段代码就完结了。

JavaScript 语法

辨别大小写

你须要晓得,ECMAScript 中所有都辨别大小写。无论是变量、函数名还是操作符,都辨别大小写。举个例子,变量 XHS 和变量 xhs 是两个不同的变量。

标识符

所谓标识符,就是变量、函数、属性或函数参数的名称。标识符能够由一或多个下列字符组成:

  • 第一个字符必须是一个字母、下划线(_)或美元符号($);
  • 剩下的其余字符能够是字母、下划线、美元符号或数字。

标识符中的字母能够是扩大 ASCII(Extended ASCII) 中的字母,也能够是 Unicode 的字母字符.

依照常规,ECMAScript 标识符应用驼峰大小写模式,即第一个单词的首字母小写,前面每个单词的首字母大写,如:

xhsRookiesxhsRookiesBoy

尽管这种写法并不是强制性的,但因为这种模式跟 ECMAScript 内置函数和对象的命名形式统一, 所以算是最佳实际。

留神 关键字、保留字、truefalsenull 不能作为标识符。

代码正文

JavaScript 中有两种正文形式:单行正文和多行正文。

正文的代码在程序中不会执行

单行正文以两个斜杠字符结尾,如:

// 单行正文

多行正文以一个斜杠和一个星号(/*)结尾,以它们的反向组合(*/)结尾,如:

/* 这是多行       正文 */

严格模式

ECMAScript 5 减少了严格模式(strict mode)的概念。严格模式是一种不同的 JavaScript 解析和执行模型,ECMAScript 3 的一些不标准写法在这种模式下会被解决,对于不平安的流动将抛出谬误。要对整个脚本启用严格模式,在脚本结尾加上这一行:

'use strict'

尽管看起来像个没有赋值给任何变量的字符串,但它其实是一个预处理指令。任何反对 JavaScript 的引擎看到它都会切换到严格模式。抉择这种语法模式的目标是不毁坏 ECMAScript 3 语法。

也能够独自指定一个函数在严格模式下执行,只有把这个预处理指令放到函数体结尾即可:

function doSomething() {  'use strict'  // 函数体}

严格模式会影响 JavaScript 执行的很多方面,所有古代浏览器都反对严格模式。

语句

ECMAScript 中的语句以分号结尾。省略分号意味着由解析器确定语句在哪里结尾,如上面的例子所示:

var sum = a + b // 没有分号也无效,但不举荐var diff = a - b // 加分号无效,举荐

即便语句开端的分号不是必须的,也应该加上。记着加分号有助于避免省略造成的问题,比方能够防止输出内容不残缺。此外,加分号也便于开发者通过删除空行来压缩代码(如果没有结尾的分号,只删除空行,则会导致语法错误)。加分号也有助于在某些状况下晋升性能,因为解析器会尝试在适合的地位补上分号以纠正语法错误。

关键字与保留字

ECMA-262 形容了一组保留的关键字,这些关键字有非凡用处,比方示意管制语句的开始和完结,或者执行特定的操作。依照规定,保留的关键字不能用作标识符或属性名。

break       do          in            typeofcase        else        instanceof    varcatch       export      new           voidclass       extends     return        whileconst       finally     super         withcontinue    for         switch        yielddebugger    function    thisdefault     if          throwdelete      import      try

标准中也形容了一组将来的保留字,同样不能用作标识符或属性名。尽管保留字在语言中没有特定用处,但它们是保留给未来做关键字用的。以下是 ECMA-262 第 6 版为未来保留的所有词汇。

始终保留:

enum

严格模式下保留

implements  package     publicinterface   protected   staticlet         private

模块代码中保留

await

申明变量并赋值

JavaScript 中,有 3 个关键字能够申明变量: varconstlet。其中,varECMAScript 的所有版本中都能够应用,而 constlet 只能在 ECMAScript 6 (将在前面学到) 及更晚的版本中应用。

var 关键字

要定义变量,能够应用 var 关键字,后跟变量名:

var xhsRookies

这行代码定义了一个名为 xhsRookies 的变量,能够用它保留任何类型的值。ECMAScript 实现变量初始化,因而能够同时定义变量并设置它的值:

var xhsRookies = 'hi'

xhsRookies 被定义为一个保留字符串值 hi 的变量。像这样初始化变量不会将它标识为字符串类型,只是一个简略的赋值而已。随后,不仅能够扭转保留的值,也能够扭转值的类型:

var xhsRookies = 'hi'xhsRookies = 100 // 非法,但不举荐

在这个例子中,变量 xhsRookies 首先被定义为一个保留字符串值 hi 的变量,而后又被重写为保留了数值 100 。尽管不举荐扭转变量保留值的类型,但这在 ECMAScript 中是齐全无效的。

1. var 申明作用域

应用 var 操作符定义的变量会成为蕴含它的函数的局部变量。比方,应用 var 在一个函数外部定义一个变量,就意味着该变量将在函数退出时被销毁:

function xhsTest() {  var xhsRookies = 'hi' // 局部变量}xhsTest()console.log(xhsRookies) // 出错!

这里,xhsRookies 变量是在函数外部应用 var 定义的。函数叫 xhsTest(),调用它会创立这个变量并给它赋值。调用之后变量随即被销毁,因而示例中的最初一行会导致谬误。不过,在函数内定义变量时省略 var 操作符,能够创立一个全局变量:

function xhsTest() {  xhsRookies = 'hi' // 全局变量}xhsTest()console.log(xhsRookies) // "hi"

去掉之前的 var 之后,xhsRookies 就变成了全局变量。只有调用一次函数 xhsTest(),就会定义这个变量,并且能够在函数内部拜访到。

尽管能够通过省略 var 操作符定义全局变量,但不举荐这么做。在部分作用域中定义的全局变量很难保护,也会造成困惑。

如果须要定义多个变量,能够在一条语句中用逗号分隔每个变量(及可选的初始化):

var xhsRookies = 'hi',  xhsFound = false,  xhsNumber = 29

这里定义并初始化了 3 个变量。

2. var 申明晋升

应用 var 时,上面的代码不会报错。这是因为应用这个关键字申明的变量会主动晋升到块作用域 5 顶部:

{  console.log(xhsNumber) // undefined  var xhsNumber = 26}

之所以不会报错,是因为 ECMAScript 运行时把它看成等价于如下代码:

{  var xhsNumber  console.log(xhsNumber) // undefined  xhsNumber = 26}

这就是所谓的“晋升”(hoist),也就是把所有变量申明都拉到块作用域的顶部。

let 申明

letvar 的作用差不多,但有着十分重要的区别。最显著的区别是,let 申明的范畴是块作用域, 而 var 申明的范畴是函数作用域。

{  var xhsRookies = 'xhs-rookies'  console.log(xhsRookies) // xhs-rookies}console.log(xhsRookies) // xhs-rookies
{  let xhsNumber = 26  console.log(xhsNumber) // 26}console.log(xhsNumber) // ReferenceError: xhsNumber 没有定义

在这里,xhsNumber 变量之所以不能在块作用域内部被援用,是因为它的作用域仅限于该块外部。块作用域是函数作用域的子集,因而实用于 var 的作用域限度同样也实用于 let

let也不容许同一个块作用域中呈现冗余申明。这样会导致报错:

var xhsRookiesvar xhsRookieslet xhsNumberlet xhsNumber // SyntaxError;标识符xhsNumber曾经申明过了

当然,JavaScript 引擎会记录用于变量申明的标识符及其所在的块作用域,因而嵌套应用雷同的标识符不会报错,而这是因为同一个块中没有反复申明:

var xhsRookies = 'xhs-rookies'console.log(xhsRookies) // 'xhs-rookies'{  var xhsRookies = 'xhs-rookies-boy'  console.log(xhsRookies) // 'xhs-rookies-boy'}let xhsNumber = 30console.log(xhsNumber) // 30{  let xhsNumber = 26  console.log(xhsNumber) // 26}

对申明冗余报错不会因混用 letvar 而受影响。这两个关键字申明的并不是不同类型的变量, 它们只是指出变量在相干作用域如何存在。

var xhsRookieslet xhsRookies // SyntaxErrorlet xhsNumbervar xhsNumber // SyntaxError

1. 全局申明

var 关键字不同,应用 let 在全局作用域中申明的变量不会成为 window 对象的属性(var 申明的变量则会)。

var xhsRookies = 'xhsRookies'console.log(window.xhsRookies) // 'xhsRookies'let xhsNumber = 26console.log(window.xhsNumber) // undefined

不过,let 申明依然是在全局作用域中产生的,相应变量会在页面的生命周期内存续。因而,为了 防止 SyntaxError,必须确保页面不会反复申明同一个变量。

2. let 作用域

let呈现之前,代码块中定义的迭代变量会渗透到内部:

{  var xhs = 5}console.log(xhs) // 5

改成应用 let 之后,这个问题就隐没了,因为 let 变量的作用域仅限于代码块外部:

{  let xhs = 0}console.log(xhs) // ReferenceError: xhs 没有定义

const 申明

const 的行为与 let 基本相同,惟一一个重要的区别是用它申明变量时必须同时初始化变量,且尝试批改 const 申明的变量会导致运行时谬误。

const xhsNumber = 26xhsNumber = 36 // TypeError: 给常量赋值// const 也不容许反复申明const xhsRookies = 'xhs-rookies'const xhsRookies = 'xhs-rookies-boy' // SyntaxError// const 申明的作用域也是块const xhsRookies = 'xhs-rookies'console.log(xhsRookies) // xhs-rookies

变量命名规定

  1. 严格辨别大小写(大写的变量和小写的变量是不同的变量);
  2. 变量名能够由数字、字母(大小写都能够)、下划线、美元符($)组成,然而不能以数字结尾;
  3. 不能是 javascript 中的关键字和保留字,如:ifelsefunction 等;
  4. 变量名须要有意义,即语义化,加强代码可读性,比方:存储年龄用 age,姓名用 name,能够避免过段时间就不了解代码是什么了,也能够避免单干时他人看不懂;
  5. 应用驼峰命名法:从第二个单词开始,首字母大写,如用户集体数据(userPersonalData);

题目自测

一:下列代码输入后果是什么?

var xhsRookies = 'hello'function textFun() {  var xhsRookies = 'hi'}console.log(xhsRookies)
  • A. hello
  • B. hi
  • C. hi hello
  • D. hello hi

二: 下列代码输入后果是什么?

console.log(xhsRookies)var xshRookies = 'xhs-rookies'console.log(xhsNumber)let xhsNumber = 26

三: 下列代码输入后果是什么?

const xhsNumber = 26xhsNumber = 36console.log(xhsNumber)

题目解析

一、

Answer:A

这道题考查的是 var 申明作用域,在第一行 xhsRookies 变量在 textFun 函数作用域外应用 var 定义的,第三行 xhsRookies 变量是在 textFun 作用域外部应用 var 定义的。所以最初一行输入 xhsRookies 其实是第一行定义的,后果是:hello

二、

Answer:

undefined

ReferenceError: Cannot access 'xhsNumber' before initialization

此题考查的是变量的晋升,输入 xshRookies 时,因为 xshRookies 应用 var 申明的,存在变量晋升,所以在输入前会认为 var xshRookies 并未赋值,所以是undefind;在解析代码时,JavaScript 引擎也会留神呈现在块前面的 let 申明,只不过在此之前不能以任何形式来援用未声明的变量。在 let 申明之前的执行霎时被称为“暂时性死区”(temporal dead zone),在此阶段援用任何前面才申明的变量都会抛出 ReferenceError

三、

Answer:

TypeError: Assignment to constant variable.

此题考查的是 const 申明特点,用它申明变量时必须同时初始化变量,且尝试批改 const 申明的变量会导致运行时谬误。