JavaScript系列一:语言基础

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

前言

在开始学习以前,咱们想要告诉您的是,本文章是对JavaScript语言知识中 "语言基础-语法和变量" 部分的总结,若是您已掌握下面知识事项,则可跳过此环节直接进入题目练习javascript

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

汇总总结

第一段代码

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

console.log('Hello JavaScript!')

你能猜到这段代码的结果吗?这段代码的操做就是在控制台输出结果是 Hello JavaScript!,到这里第一段代码就结束了。java

JavaScript 语法

区分大小写

你须要知道,ECMAScript 中一切都区分大小写。不管是变量、函数名仍是操做符,都区分大小写。举个例子,变量 XHS 和变量 xhs 是两个不一样的变量。浏览器

标识符

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

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

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

按照惯例,ECMAScript 标识符使用驼峰大小写形式,即第一个单词的首字母小写,后面每一个单词的首字母大写,如:函数

xhsRookies
xhsRookiesBoy

虽然这种写法并非强制性的,但由于这种形式跟 ECMAScript 内置函数和对象的命名方式一致, 因此算是最佳实践。性能

注意 关键字、保留字、 truefalsenull 不能做为标识符。

代码注释

JavaScript 中有两种注释方式:单行注释和多行注释。学习

注释的代码在程序中不会执行

单行注释以两个斜杠字符开头,如:this

// 单行注释

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

/* 这是多行
       注释 */

严格模式

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            typeof
case        else        instanceof    var
catch       export      new           void
class       extends     return        while
const       finally     super         with
continue    for         switch        yield
debugger    function    this
default     if          throw
delete      import      try

规范中也描述了一组将来的保留字,一样不能用做标识符或属性名。虽然保留字在语言中没有特定用途,但它们是保留给未来作关键字用的。如下是 ECMA-262 第 6 版为未来保留的全部词汇。

始终保留:

enum

严格模式下保留

implements  package     public
interface   protected   static
let         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 xhsRookies
var xhsRookies
let xhsNumber
let 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 = 30
console.log(xhsNumber) // 30
{
  let xhsNumber = 26
  console.log(xhsNumber) // 26
}

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

var xhsRookies
let xhsRookies // SyntaxError
let xhsNumber
var xhsNumber // SyntaxError

1. 全局声明

var 关键字不一样,使用 let 在全局做用域中声明的变量不会成为 window 对象的属性(var 声明的变量则会)。

var xhsRookies = 'xhsRookies'
console.log(window.xhsRookies) // 'xhsRookies'
let xhsNumber = 26
console.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 = 26
xhsNumber = 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 = 26
xhsNumber = 36
console.log(xhsNumber)

题目解析

1、

Answer:A

这道题考查的是 var 声明做用域,在第一行 xhsRookies 变量在 textFun 函数做用域外使用 var 定义的,第三行 xhsRookies 变量是在 textFun 做用域内部使用 var 定义的。因此最后一行输出 xhsRookies 实际上是第一行定义的,结果是:hello

2、

Answer:

undefined

ReferenceError: Cannot access 'xhsNumber' before initialization

此题考查的是变量的提高,输出 xshRookies 时,因为 xshRookies 使用 var 声明的,存在变量提高,因此在输出前会认为 var xshRookies 并未赋值,因此是undefind;在解析代码时,JavaScript 引擎也会注意出如今块后面的 let 声明,只不过在此以前不能以任何方式来引用未声明的变量。在 let 声明以前的执行瞬间被称为“暂时性死区”(temporal dead zone),在此阶段引用任何后面才声明的变量都会抛出 ReferenceError

3、

Answer:

TypeError: Assignment to constant variable.

此题考查的是 const 声明特色,用它声明变量时必须同时初始化变量,且尝试修改 const 声明的变量会致使运行时错误。

相关文章
相关标签/搜索